diff options
Diffstat (limited to 'pkg/images/tv/imedit')
27 files changed, 3029 insertions, 0 deletions
diff --git a/pkg/images/tv/imedit/bpmedit.cl b/pkg/images/tv/imedit/bpmedit.cl new file mode 100644 index 00000000..01d5f7aa --- /dev/null +++ b/pkg/images/tv/imedit/bpmedit.cl @@ -0,0 +1,69 @@ +# BPMEDIT -- Edit BPM masks. + +procedure bpmedit (images) + +string images {prompt="List of images"} +string bpmkey = "BPM" {prompt="Keyword with mask name"} +int frame = 1 {prompt="Display frame with mask overlay"} +int refframe = 2 {prompt="Display frame without mask overlay"} +string command = "display $image $frame over=$mask erase=$erase ocol='1-10=red,green' fill-" {prompt="Display command"} +bool display = yes {prompt="Interactive display?"} +string cursor = "" {prompt="Cursor input"} + +struct *fd + +begin + int i1 + file im, bpm, temp + struct dispcmd + + set imedit_help = "tv$imedit/bpmedit.key" + + temp = mktemp ("tmp$iraf") + + sections (images, option="fullname", > temp) + + fd = temp + while (fscan (fd, im) != EOF) { + bpm = ""; hselect (im, bpmkey, yes) | scan (bpm) + if (bpm == "") { + printf ("WARNING: No %s keyword (%s)\n", bpmkey, im) + next + } + if (imaccess(bpm)==NO) { + printf ("WARNING: Can't access mask (%s)\n", bpm) + next + } + + if (display) { + # Override certain display parameters. + display.bpdisplay="none" + display.fill = no + + # Set display command. + dispcmd = command + i1 = strstr ("$image", dispcmd) + if (i1 > 0) + dispcmd = substr (dispcmd, 1, i1-1) // im // + substr (dispcmd, i1+6, 1000) + i1 = strstr ("$frame", dispcmd) + if (i1 > 0) + dispcmd = substr (dispcmd, 1, i1-1) // frame // + substr (dispcmd, i1+6, 1000) + i1 = strstr ("$mask", dispcmd) + if (i1 > 0) + dispcmd = substr (dispcmd, 1, i1-1) // "$image" // + substr (dispcmd, i1+5, 1000) + i1 = strstr (">", dispcmd) + if (i1 == 0) + dispcmd += " >& dev$null" + + display (im, refframe, over="", >& "dev$null") + imedit (bpm, "", command=dispcmd, display=display, + cursor=cursor, search=0) + } else + imedit (bpm, "", command=dispcmd, display=display, + cursor=cursor, search=0) + } + fd = ""; delete (temp, verify-) +end diff --git a/pkg/images/tv/imedit/bpmedit.key b/pkg/images/tv/imedit/bpmedit.key new file mode 100644 index 00000000..0d660732 --- /dev/null +++ b/pkg/images/tv/imedit/bpmedit.key @@ -0,0 +1,51 @@ + BPMEDIT CURSOR KEYSTROKE COMMANDS + +The following are the useful commands for BPMEDIT. Note all +the commands for IMEDIT are available but only those shown +here should be used for editing pixel masks. + + ? Print help + : Colon commands (see below) + i Initialize (start over without saving changes) + q Quit and save changes + r Redraw image display + + Increase radius by one + - Decrease radius by one + I Interrupt task immediately + Q Quit without saving changes + +The following editing options are available. Rectangular +and vector regions are specified with two positions and +aperture regions are specified by one position. The current +aperture type (circular or square) is used in the latter +case. All the following substitute the new value set for +the "value" parameter (see :value). Some replace all pixels +within the mask that have the same pixel value as the value +at the cursor position. + + d Set rectangle to "value" + e Set aperture to "value" + u Undo last change (see also 'i', 'j', and 'k') + v Set vector to "value" + = Replace pixels = to "cursor value" to "value" + < Replace pixels < or = to "cursor value" to "value" + > Replace pixels > than or = to "cursor value" to "value" + + + BPMEDIT COLON COMMANDS + +The colon either print the current value of a parameter when +there is no value or set the parameter to the specified +value. + +aperture [type] Aperture type (circular|square) +autodisplay [yes|no] Automatic image display? +command [string] Display command +display [yes|no] Display image? +eparam Edit parameters +radius [value] Aperture radius +value [value] Constant substitution value +minvalue [value] Minimum value for modification (INDEF=minimum) +maxvalue [value] Maximum value for modification (INDEF=maximum) +write [name] Write changes to name + diff --git a/pkg/images/tv/imedit/epbackground.x b/pkg/images/tv/imedit/epbackground.x new file mode 100644 index 00000000..339de946 --- /dev/null +++ b/pkg/images/tv/imedit/epbackground.x @@ -0,0 +1,71 @@ +include "epix.h" + +# EP_BACKGROUND -- Replace aperture by background values. +# The aperture is first centered. The background is determined from a +# annulus buffered from the aperture and of a specified width. The +# background is obtained by fitting a surface. Noise may be added +# using a gaussian or by histogram sampling. + +procedure ep_background (ep, ap, xa, ya, xb, yb) + +pointer ep # EPIX structure +int ap # Aperture type +int xa, ya, xb, yb # Aperture coordinates + +int i, x1, x2, y1, y2 +pointer mask, x, y, w, gs + +begin + i = max (5., + abs (EP_SEARCH(ep)) + EP_BUFFER(ep) + EP_WIDTH(ep) + 1) + x1 = min (xa, xb) - i + x2 = max (xa, xb) + i + y1 = min (ya, yb) - i + y2 = max (ya, yb) + i + call ep_gdata (ep, x1, x2, y1, y2) + if (EP_OUTDATA(ep) != NULL) { + call malloc (mask, EP_NPTS(ep), TY_INT) + call malloc (x, EP_NPTS(ep), TY_REAL) + call malloc (y, EP_NPTS(ep), TY_REAL) + call malloc (w, EP_NPTS(ep), TY_REAL) + + call ep_search (ep, Memr[EP_OUTDATA(ep)], EP_NX(ep), EP_NY(ep), + ap, xa, ya, xb, yb) + call ep_mask (ep, mask, ap, xa, ya, xb, yb) + call ep_gsfit (ep, Memr[EP_OUTDATA(ep)], Memi[mask], Memr[x], + Memr[y], Memr[w], EP_NX(ep), EP_NY(ep), gs) + call ep_bg (Memr[EP_OUTDATA(ep)], Memi[mask], + Memr[x], Memr[y], EP_NPTS(ep), gs) + call ep_noise (EP_SIGMA(ep), Memr[EP_OUTDATA(ep)], + Memi[mask], Memr[x], Memr[y], EP_NPTS(ep), gs) + + call mfree (mask, TY_INT) + call mfree (x, TY_REAL) + call mfree (y, TY_REAL) + call mfree (w, TY_REAL) + call gsfree (gs) + } +end + + +# EP_BG -- Replace aperture pixels by the background surface fit values. + +procedure ep_bg (data, mask, x, y, npts, gs) + +real data[npts] # Data subraster +int mask[npts] # Mask subraster +real x[npts], y[npts] # Coordinates +int npts # Number of points +pointer gs # Surface pointer + +int i +real gseval() + +begin + if (gs == NULL) + return + + do i = 1, npts + if (mask[i] == 1) + data[i] = gseval (gs, x[i], y[i]) +end diff --git a/pkg/images/tv/imedit/epcol.x b/pkg/images/tv/imedit/epcol.x new file mode 100644 index 00000000..e71d5e47 --- /dev/null +++ b/pkg/images/tv/imedit/epcol.x @@ -0,0 +1,80 @@ +include "epix.h" + +# EP_COL -- Replace aperture by column interpolation from background annulus. +# The aperture is first centered. The interpolation is across columns +# from the nearest pixel in the background annulus. Gaussian Noise may +# be added. + +procedure ep_col (ep, ap, xa, ya, xb, yb) + +pointer ep # EPIX pointer +int ap # Aperture type +int xa, ya, xb, yb # Aperture coordinates + +int i, x1, x2, y1, y2 +pointer mask, gs + +begin + i = abs (EP_SEARCH(ep)) + EP_BUFFER(ep) + 1 + x1 = min (xa, xb) - i + x2 = max (xa, xb) + i + y1 = min (ya, yb) + y2 = max (ya, yb) + call ep_gdata (ep, x1, x2, y1, y2) + if (EP_OUTDATA(ep) != NULL) { + call malloc (mask, EP_NPTS(ep), TY_INT) + + call ep_search (ep, Memr[EP_OUTDATA(ep)], EP_NX(ep), + EP_NY(ep), ap, xa, ya, xb, yb) + call ep_mask (ep, mask, ap, xa, ya, xb, yb) + call ep_col1 (Memr[EP_OUTDATA(ep)], Memi[mask], EP_NX(ep), + EP_NY(ep)) + if (!IS_INDEF (EP_SIGMA(ep))) + call ep_noise (EP_SIGMA(ep), Memr[EP_OUTDATA(ep)], + Memi[mask], Memr[EP_OUTDATA(ep)], Memr[EP_OUTDATA(ep)], + EP_NPTS(ep), gs) + + call mfree (mask, TY_INT) + } +end + + +# EP_COL1 -- Do column interpolation. + +procedure ep_col1 (data, mask, nx, ny) + +real data[nx,ny] # Data subraster +int mask[nx,ny] # Mask subraster +int nx, ny # Number of points + +int i, j, xa, xb, xc, xd +real a, b + +begin + do i = 1, ny { + for (xa=1; xa<=nx && mask[xa,i]!=1; xa=xa+1) + ; + if (xa > nx) + next + for (xb=nx; xb>xa && mask[xb,i]!=1; xb=xb-1) + ; + for (xc=xa; xc>=1 && mask[xc,i]!=2; xc=xc-1) + ; + for (xd=xb; xd<=nx && mask[xd,i]!=2; xd=xd+1) + ; + if (xc < 1 && xd > nx) + next + else if (xc < 1) + do j = xa, xb + data[j,i] = data[xd,i] + else if (xd > nx) + do j = xa, xb + data[j,i] = data[xc,i] + else { + a = data[xc,i] + b = (data[xd,i] - a) / (xd - xc) + do j = xa, xb + data[j,i] = a + b * (j - xc) + } + } +end diff --git a/pkg/images/tv/imedit/epcolon.x b/pkg/images/tv/imedit/epcolon.x new file mode 100644 index 00000000..51765889 --- /dev/null +++ b/pkg/images/tv/imedit/epcolon.x @@ -0,0 +1,335 @@ +include "epix.h" + +# List of colon commands. +define CMDS "|angh|angv|aperture|autodisplay|autosurface|buffer|command|\ + |display|eparam|graphics|input|output|radius|search|sigma|\ + |value|minvalue|maxvalue|width|write|xorder|yorder|" + +define ANGH 1 # Horizontal viewing angle +define ANGV 2 # Vertical viewing angle +define APERTURE 3 # Aperture type +define AUTODISPLAY 4 # Automatic display? +define AUTOSURFACE 5 # Automatic surface graph? +define BUFFER 6 # Background buffer width +define COMMAND 7 # Display command +define DISPLAY 9 # Display image? +define EPARAM 10 # Eparam +define GRAPHICS 11 # Graphics device +define INPUT 12 # Input image +define OUTPUT 13 # Output image +define RADIUS 14 # Aperture radius +define SEARCH 15 # Search radius +define SIGMA 16 # Noise sigma +define VALUE 18 # Constant substitution value +define MINVALUE 19 # Minimum value for replacement +define MAXVALUE 20 # Maximum value for replacement +define WIDTH 21 # Background width +define WRITE 22 # Write output +define XORDER 23 # X order +define YORDER 24 # Y order + +# EP_COLON -- Respond to colon commands. +# The changed parameters are written to the parameter file and +# to the optional log file. + +procedure ep_colon (ep, cmdstr, newimage) + +pointer ep # EPIX structure +char cmdstr[ARB] # Colon command +int newimage # New image? + +int ival, ncmd +real rval +bool bval +pointer sp, cmd + +bool strne() +int nscan(), strdic(), btoi(), imaccess() +pointer immap() + +begin + call smark (sp) + call salloc (cmd, SZ_LINE, TY_CHAR) + + # Scan the command string and get the first word. + call sscan (cmdstr) + call gargwrd (Memc[cmd], SZ_LINE) + ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, CMDS) + + switch (ncmd) { + case ANGH: + call gargr (rval) + if (nscan() == 1) { + call printf ("angh %g\n") + call pargr (EP_ANGH(ep)) + } else { + EP_ANGH(ep) = rval + call clputr ("angh", EP_ANGH(ep)) + } + case ANGV: + call gargr (rval) + if (nscan() == 1) { + call printf ("angv %g\n") + call pargr (EP_ANGV(ep)) + } else { + EP_ANGV(ep) = rval + call clputr ("angv", EP_ANGV(ep)) + } + case APERTURE: + call gargwrd (Memc[cmd], SZ_FNAME) + if (nscan() == 1) { + call printf ("aperture %s\n") + switch (EP_APERTURE(ep)) { + case APCIRCULAR: + call pargstr ("circular") + case APSQUARE: + call pargstr ("square") + } + } else { + ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, APTYPES) + if (ncmd > 0) { + EP_APERTURE(ep) = ncmd + call clpstr ("aperture", Memc[cmd]) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":aperture %s\n") + call pargstr (Memc[cmd]) + } + } else + call printf ("Unknown aperture type\n") + } + case AUTODISPLAY: + call gargb (bval) + if (nscan() == 1) { + if (EP_AUTODISPLAY(ep) == YES) + call printf ("autodisplay yes\n") + else + call printf ("autodisplay no\n") + } else { + EP_AUTODISPLAY(ep) = btoi (bval) + call clputb ("autodisplay", bval) + } + case AUTOSURFACE: + call gargb (bval) + if (nscan() == 1) { + if (EP_AUTOSURFACE(ep) == YES) + call printf ("autosurface yes\n") + else + call printf ("autosurface no\n") + } else { + EP_AUTOSURFACE(ep) = btoi (bval) + call clputb ("autosurface", bval) + } + case BUFFER: + call gargr (rval) + if (nscan() == 1) { + call printf ("buffer %g\n") + call pargr (EP_BUFFER(ep)) + } else { + EP_BUFFER(ep) = rval + call clputr ("buffer", EP_BUFFER(ep)) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":buffer %g\n") + call pargr (EP_BUFFER(ep)) + } + } + case COMMAND: + call gargwrd (Memc[cmd], SZ_FNAME) + if (nscan() == 1) { + call printf ("command %s\n") + call pargstr (EP_COMMAND(ep)) + } else { + call strcpy (Memc[cmd], EP_COMMAND(ep), EP_SZLINE) + call gargstr (Memc[cmd], SZ_FNAME) + call strcat (Memc[cmd], EP_COMMAND(ep), EP_SZFNAME) + call clpstr ("command", EP_COMMAND(ep)) + } + case DISPLAY: + call gargb (bval) + if (nscan() == 1) { + if (EP_DISPLAY(ep) == YES) + call printf ("display yes\n") + else + call printf ("display no\n") + } else { + EP_DISPLAY(ep) = btoi (bval) + call clputb ("display", bval) + } + case EPARAM: + call clcmdw ("eparam imedit") + call ep_setpars (ep) + case GRAPHICS: + call gargwrd (Memc[cmd], SZ_FNAME) + if (nscan() == 1) { + call printf ("graphics %s\n") + call pargstr (EP_GRAPHICS(ep)) + } else { + call strcpy (Memc[cmd], EP_GRAPHICS(ep), EP_SZFNAME) + call clpstr ("graphics", EP_GRAPHICS(ep)) + } + case INPUT: + call gargwrd (Memc[cmd], SZ_FNAME) + if (nscan() == 1) { + call printf ("input %s\n") + call pargstr (EP_INPUT(ep)) + } else if (strne (Memc[cmd], EP_INPUT(ep))) { + call strcpy (Memc[cmd], EP_INPUT(ep), SZ_LINE) + newimage = YES + } + case OUTPUT: + call gargwrd (Memc[cmd], SZ_FNAME) + if (nscan() == 1) { + call printf ("output %s\n") + call pargstr (EP_OUTPUT(ep)) + } else if (strne (Memc[cmd], EP_INPUT(ep))) { + if (imaccess (Memc[cmd], READ_ONLY) == YES) { + call eprintf ("%s: Output image %s exists\n") + call pargstr (EP_INPUT(ep)) + call pargstr (Memc[cmd]) + } else + call strcpy (Memc[cmd], EP_OUTPUT(ep), EP_SZFNAME) + } + case RADIUS: + call gargr (rval) + if (nscan() == 1) { + call printf ("radius %g\n") + call pargr (EP_RADIUS(ep)) + } else { + EP_RADIUS(ep) = rval + call clputr ("radius", EP_RADIUS(ep)) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":radius %g\n") + call pargr (EP_RADIUS(ep)) + } + } + case SEARCH: + call gargr (rval) + if (nscan() == 1) { + call printf ("search %g\n") + call pargr (EP_SEARCH(ep)) + } else { + EP_SEARCH(ep) = rval + call clputr ("search", EP_SEARCH(ep)) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":search %g\n") + call pargr (EP_SEARCH(ep)) + } + } + case SIGMA: + call gargr (rval) + if (nscan() == 1) { + call printf ("sigma %g\n") + call pargr (EP_SIGMA(ep)) + } else { + EP_SIGMA(ep) = rval + call clputr ("sigma", EP_SIGMA(ep)) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":sigma %g\n") + call pargr (EP_SIGMA(ep)) + } + } + case VALUE: + call gargr (rval) + if (nscan() == 1) { + call printf ("value %g\n") + call pargr (EP_VALUE(ep)) + } else { + EP_VALUE(ep) = rval + call clputr ("value", EP_VALUE(ep)) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":value %g\n") + call pargr (EP_VALUE(ep)) + } + } + case MINVALUE: + call gargr (rval) + if (nscan() == 1) { + call printf ("minvalue %g\n") + call pargr (EP_MINVALUE(ep)) + } else { + EP_MINVALUE(ep) = rval + call clputr ("minvalue", EP_MINVALUE(ep)) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":minvalue %g\n") + call pargr (EP_MINVALUE(ep)) + } + } + case MAXVALUE: + call gargr (rval) + if (nscan() == 1) { + call printf ("maxvalue %g\n") + call pargr (EP_MAXVALUE(ep)) + } else { + EP_MAXVALUE(ep) = rval + call clputr ("maxvalue", EP_MAXVALUE(ep)) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":maxvalue %g\n") + call pargr (EP_MAXVALUE(ep)) + } + } + case WIDTH: + call gargr (rval) + if (nscan() == 1 || rval < 1.) { + call printf ("width %g\n") + call pargr (EP_WIDTH(ep)) + } else { + EP_WIDTH(ep) = max (1., rval) + call clputr ("width", EP_WIDTH(ep)) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":width %g\n") + call pargr (EP_WIDTH(ep)) + } + } + case WRITE: + call gargwrd (Memc[cmd], SZ_FNAME) + ival = YES + if (nscan() == 1) + call strcpy (EP_OUTPUT(ep), Memc[cmd], SZ_FNAME) + else if (strne (Memc[cmd], EP_INPUT(ep))) { + if (imaccess (Memc[cmd], READ_ONLY) == YES) { + call eprintf ("Image %s exists\n") + call pargstr (Memc[cmd]) + ival = NO + } + } + + if (ival == YES) { + call printf ("output %s\n") + call pargstr (Memc[cmd]) + if (imaccess (Memc[cmd], READ_ONLY) == YES) + call imdelete (Memc[cmd]) + call imunmap (EP_IM(ep)) + call ep_imcopy (EP_WORK(ep), Memc[cmd]) + EP_IM(ep) = immap (EP_WORK(ep), READ_WRITE, 0) + } + case XORDER: + call gargi (ival) + if (nscan() == 1) { + call printf ("xorder %d\n") + call pargi (EP_XORDER(ep)) + } else { + EP_XORDER(ep) = max (0, ival) + call clputi ("xorder", EP_XORDER(ep)) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":xorder %d\n") + call pargi (EP_XORDER(ep)) + } + } + case YORDER: + call gargi (ival) + if (nscan() == 1) { + call printf ("yorder %d\n") + call pargi (EP_YORDER(ep)) + } else { + EP_YORDER(ep) = max (0, ival) + call clputi ("yorder", EP_YORDER(ep)) + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), ":yorder %d\n") + call pargi (EP_YORDER(ep)) + } + } + default: + call printf ("Unrecognized or ambiguous command\007") + } + + call sfree (sp) +end diff --git a/pkg/images/tv/imedit/epconstant.x b/pkg/images/tv/imedit/epconstant.x new file mode 100644 index 00000000..0a168a19 --- /dev/null +++ b/pkg/images/tv/imedit/epconstant.x @@ -0,0 +1,51 @@ +include "epix.h" + +# EP_CONSTANT -- Replace aperture by constant value. +# The aperture is first centered. + +procedure ep_constant (ep, ap, xa, ya, xb, yb) + +pointer ep # EPIX pointer +int ap # Aperture type +int xa, ya, xb, yb # Aperture coordinates + +int i, x1, x2, y1, y2 +pointer mask + +begin + i = max (5., abs (EP_SEARCH(ep)) + 1) + x1 = min (xa, xb) - i + x2 = max (xa, xb) + i + y1 = min (ya, yb) - i + y2 = max (ya, yb) + i + call ep_gdata (ep, x1, x2, y1, y2) + if (EP_OUTDATA(ep) != NULL) { + call malloc (mask, EP_NPTS(ep), TY_INT) + + call ep_search (ep, Memr[EP_OUTDATA(ep)], EP_NX(ep), + EP_NY(ep), ap, xa, ya, xb, yb) + call ep_mask (ep, mask, ap, xa, ya, xb, yb) + call ep_constant1 (Memr[EP_OUTDATA(ep)], Memi[mask], EP_NPTS(ep), + EP_VALUE(ep)) + + call mfree (mask, TY_INT) + } +end + + +# EP_CONSTANT1 -- Replace aperture by constant value. + +procedure ep_constant1 (data, mask, npts, value) + +real data[npts] # Data subraster +int mask[npts] # Mask subraster +int npts # Number of points +real value # Substitution value + +int i + +begin + do i = 1, npts + if (mask[i] == 1) + data[i] = value +end diff --git a/pkg/images/tv/imedit/epdisplay.x b/pkg/images/tv/imedit/epdisplay.x new file mode 100644 index 00000000..1b76e5b1 --- /dev/null +++ b/pkg/images/tv/imedit/epdisplay.x @@ -0,0 +1,196 @@ +include <imhdr.h> +include "epix.h" + +# EP_DISPLAY -- Display an image using the specified command. +# This is a temporary image display interface using CLCMDW to call +# the standard display task. Image sections and the fill option +# can be used to simulate zoom. One complication is that we have to +# close the image to avoid multiple access to the image. This +# requires saving the original input subraster to allow undoing +# a change after display. + +procedure ep_display (ep, image, erase) + +pointer ep # EPIX structure +char image[ARB] # Image +bool erase # Erase + +pointer temp, immap(), imgs2r(), imps2r() + +begin + # If the output has been modified save and restore the original + # input subraster for later undoing. + + if (EP_OUTDATA(ep) != NULL) { + call malloc (temp, EP_NPTS(ep), TY_REAL) + call amovr (Memr[EP_INDATA(ep)], Memr[temp], EP_NPTS(ep)) + call imunmap (EP_IM(ep)) + call ep_command (ep, image, erase) + erase = false + EP_IM(ep) = immap (image, READ_WRITE, 0) + EP_OUTDATA(ep) = imps2r (EP_IM(ep), EP_X1(ep), + EP_X2(ep), EP_Y1(ep), EP_Y2(ep)) + EP_INDATA(ep) = imgs2r (EP_IM(ep), EP_X1(ep), + EP_X2(ep), EP_Y1(ep), EP_Y2(ep)) + call amovr (Memr[EP_INDATA(ep)], Memr[EP_OUTDATA(ep)], + EP_NPTS(ep)) + call amovr (Memr[temp], Memr[EP_INDATA(ep)], EP_NPTS(ep)) + call mfree (temp, TY_REAL) + } else { + call imunmap (EP_IM(ep)) + call ep_command (ep, image, erase) + erase = false + EP_IM(ep) = immap (image, READ_WRITE, 0) + } +end + + +define PARAMS "|$image|$erase|" +define IMAGE 1 +define ERASE 2 + +# EP_COMMAND -- Format a command with argument substitution. This +# technique allows use of some other display command (such as CONTOUR). + +procedure ep_command (ep, image, erase) + +pointer ep # EPIX structure +char image[ARB] # Image name +bool erase # Erase? + +int i, j, k, nscan(), strdic(), stridxs() +pointer sp, cmd, word + +begin + call smark (sp) + call salloc (cmd, SZ_LINE, TY_CHAR) + call salloc (word, SZ_LINE, TY_CHAR) + + call sscan (EP_COMMAND(ep)) + + Memc[cmd] = EOS + do i = 1, 100 { + call gargwrd (Memc[word], SZ_LINE) + if (nscan() != i) + break + j = stridxs ("$", Memc[word]) - 1 + if (j >= 0) { + k = strdic (Memc[word+j], Memc[word+j], SZ_LINE, PARAMS) + switch (k) { + case IMAGE: + call sprintf (Memc[word+j], SZ_LINE-j, "%s%s") + call pargstr (image) + call pargstr (EP_SECTION(ep)) + case ERASE: + call sprintf (Memc[word+j], SZ_LINE-j, "%b") + call pargb (erase) + } + } + call strcat (Memc[word], Memc[cmd], SZ_LINE) + call strcat (" ", Memc[cmd], SZ_LINE) + } + + if (i > 1) { + call clcmdw (Memc[cmd]) + erase = false + } + + call sfree (sp) +end + + +# EP_ZOOM -- Set an image section centered on the cursor for possible zooming. +# Zoom is simulated by loading a subraster of the image. If the image display +# supports fill the frame this will give the effect of a zoom. + +procedure ep_zoom (ep, xa, ya, xb, yb, key, erase) + +pointer ep # EPIX structure +int xa, ya # Cursor +int xb, yb # Cursor +int key # Cursor key +bool erase # Erase? + +real zoom +int nc, nl, nx, ny, zx, zy, x1, x2, y1, y2 +data zoom/1./ + +begin + erase = true + + switch (key) { + case '0': + zoom = 1. + case 'E': + nc = IM_LEN(EP_IM(ep),1) + nl = IM_LEN(EP_IM(ep),2) + nx = abs (xa - xb) + 1 + ny = abs (ya - yb) + 1 + zoom = max (1., min (nc / real (nx), nl / real (ny))) + zx = (xa + xb) / 2. + zy = (ya + yb) / 2. + case 'P': + zoom = max (1., zoom / 2) + zx = xa + zy = ya + case 'Z': + zoom = 2 * zoom + zx = xa + zy = ya + } + + if (zoom == 1.) { + EP_SECTION(ep) = EOS + return + } + + nc = IM_LEN(EP_IM(ep),1) + nl = IM_LEN(EP_IM(ep),2) + nx = nc / zoom + ny = nl / zoom + + switch (key) { + case '1': + zx = zx + .4 * nx + zy = zy + .4 * ny + case '2': + zy = zy + .4 * ny + case '3': + zx = zx - .4 * nx + zy = zy + .4 * ny + case '4': + zx = zx + .4 * nx + case '5', 'r', 'R': + erase = false + case '6': + zx = zx - .4 * nx + case '7': + zx = zx + .4 * nx + zy = zy - .4 * ny + case '8': + zy = zy - .4 * ny + case '9': + zx = zx - .4 * nx + zy = zy - .4 * ny + } + + # Insure the section is in bounds. + x1 = max (1, zx - nx / 2) + x2 = min (nc, x1 + nx) + x1 = max (1, x2 - nx) + y1 = max (1, zy - ny / 2) + y2 = min (nl, y1 + ny) + y1 = max (1, y2 - ny) + + zx = (x1 + x2) / 2 + zy = (y1 + y2) / 2 + nx = x2 - x1 + 1 + ny = y2 - y1 + 1 + + # Format the image section. + call sprintf (EP_SECTION(ep), EP_SZFNAME, "[%d:%d,%d:%d]") + call pargi (x1) + call pargi (x2) + call pargi (y1) + call pargi (y2) +end diff --git a/pkg/images/tv/imedit/epdosurface.x b/pkg/images/tv/imedit/epdosurface.x new file mode 100644 index 00000000..70866bb1 --- /dev/null +++ b/pkg/images/tv/imedit/epdosurface.x @@ -0,0 +1,35 @@ +include "epix.h" + +# EP_DOSURFACE -- Display surface plots. +# There are two modes. If there is no output subraster then just +# display the input subraster otherwise display both. The orientation +# is given by the user. + +procedure ep_dosurface (ep) + +pointer ep # EPIX structure +pointer gp, gopen() + +begin + if (EP_INDATA(ep) == NULL && EP_OUTDATA(ep) == NULL) { + call eprintf ("No region defined\n") + return + } + + gp = gopen (EP_GRAPHICS(ep), NEW_FILE, STDGRAPH) + + if (EP_OUTDATA(ep) == NULL) { + call gsview (gp, 0.03, 0.98, 0.03, 0.98) + call ep_surface (gp, Memr[EP_INDATA(ep)], EP_NX(ep), EP_NY(ep), + EP_ANGH(ep), EP_ANGV(ep)) + } else { + call gsview (gp, 0.03, 0.48, 0.03, 0.98) + call ep_surface (gp, Memr[EP_INDATA(ep)], EP_NX(ep), EP_NY(ep), + EP_ANGH(ep), EP_ANGV(ep)) + call gsview (gp, 0.53, 0.98, 0.03, 0.98) + call ep_surface (gp, Memr[EP_OUTDATA(ep)], EP_NX(ep),EP_NY(ep), + EP_ANGH(ep), EP_ANGV(ep)) + } + + call gclose (gp) +end diff --git a/pkg/images/tv/imedit/epgcur.x b/pkg/images/tv/imedit/epgcur.x new file mode 100644 index 00000000..5e424a65 --- /dev/null +++ b/pkg/images/tv/imedit/epgcur.x @@ -0,0 +1,127 @@ +include "epix.h" + +# EP_GCUR -- Get EPIX cursor value. +# This is an interface between the standard cursor input and EPIX. It +# returns an aperture consisting of an aperture type and the two integer +# pixel corners containing the aperture. This interface also provides +# for interpreting the FIXPIX type files. A default key may be +# supplied which allows simple X-Y files to be read. + +int procedure ep_gcur (ep, ap, x1, y1, x2, y2, key, strval, maxch) + +pointer ep # EPIX structure +int ap # Aperture type +int x1, y1, x2, y2 # Corners of aperture +int key # Keystroke value of cursor event +char strval[ARB] # String value, if any +int maxch + +real a, b, c, d, e +pointer sp, buf, ip +int nitems, wcs +int ctor(), clglstr(), clgcur() + +begin + # FIXPIX format consists of a rectangle with column and line ranges. + # The key returned is for interpolation across the narrow dimension + # of the rectangle. + + if (EP_FIXPIX(ep) == YES) { + call smark (sp) + call salloc (buf, SZ_LINE, TY_CHAR) + + # Read the list structured string. + if (clglstr ("cursor", Memc[buf], SZ_LINE) == EOF) { + call sfree (sp) + return (EOF) + } + + ip = buf + nitems = 0 + if (ctor (Memc, ip, a) > 0) + nitems = nitems + 1 + if (ctor (Memc, ip, b) > 0) + nitems = nitems + 1 + if (ctor (Memc, ip, c) > 0) + nitems = nitems + 1 + if (ctor (Memc, ip, d) > 0) + nitems = nitems + 1 + + e = max (a, b) + a = min (a, b) + b = e + e = max (c, d) + c = min (c, d) + d = e + x1 = nint(a) + y1 = nint(c) + x2 = nint(b) + y2 = nint(d) + ap = APRECTANGLE + if (x2 - x1 <= y2 - y1) + key = 'c' + else + key = 'l' + + call sfree (sp) + return (nitems) + } + + # The standard cursor value is read for centered apertures and + # for two values are read for rectangular apertures. The + # returned coordinates are properly defined. + + key = EP_DEFAULT(ep) + strval[1] = EOS + nitems = clgcur ("cursor", a, b, wcs, key, strval, maxch) + switch (key) { + case 'a', 'c', 'd', 'l', 'f', 'j', 'v': + call printf ("again:") + nitems = clgcur ("cursor", c, d, wcs, key, strval, SZ_LINE) + call printf ("\n") + if (!IS_INDEF(a)) + x1 = nint (a) + if (!IS_INDEF(b)) + y1 = nint (b) + if (!IS_INDEF(c)) + x2 = nint (c) + if (!IS_INDEF(d)) + y2 = nint (d) + if (key == 'f' || key == 'v') { + if (abs (x2-x1) > abs (y2-y1)) + ap = APLDIAG + else + ap = APCDIAG + } else + ap = APRECTANGLE + case 'b', 'e', 'k', 'm', 'n', 'p', 's', ' ': + if (!IS_INDEF(a)) { + x1 = nint (a - EP_RADIUS(ep)) + x2 = nint (a + EP_RADIUS(ep)) + } + if (!IS_INDEF(b)) { + y1 = nint (b - EP_RADIUS(ep)) + y2 = nint (b + EP_RADIUS(ep)) + } + ap = EP_APERTURE(ep) + case 'E': + call printf ("again:") + nitems = clgcur ("cursor", c, d, wcs, key, strval, SZ_LINE) + call printf ("\n") + if (!IS_INDEF(a)) + x1 = nint (a) + if (!IS_INDEF(b)) + y1 = nint (b) + if (!IS_INDEF(c)) + x2 = nint (c) + if (!IS_INDEF(d)) + y2 = nint (d) + default: + if (!IS_INDEF(a)) + x1 = nint (a) + if (!IS_INDEF(b)) + y1 = nint (b) + } + + return (nitems) +end diff --git a/pkg/images/tv/imedit/epgdata.x b/pkg/images/tv/imedit/epgdata.x new file mode 100644 index 00000000..163d7478 --- /dev/null +++ b/pkg/images/tv/imedit/epgdata.x @@ -0,0 +1,70 @@ +include <imhdr.h> +include "epix.h" + +# EP_GDATA -- Get input and output image subrasters with boundary checking. +# Null pointer are returned if entirely out of bounds. + +procedure ep_gdata (ep, x1, x2, y1, y2) + +pointer ep # EPIX pointer +int x1, x2, y1, y2 # Subraster limits + +int nc, nl +pointer im, imgs2r(), imps2r() + +begin + im = EP_IM(ep) + nc = IM_LEN(im,1) + nl = IM_LEN(im,2) + + if (x2 < 1 || x1 >= nc || y2 < 1 || y1 >= nl) { + call eprintf ("Pixel out of bounds\n") + EP_INDATA(ep) = NULL + EP_OUTDATA(ep) = NULL + return + } + + EP_X1(ep) = max (1, x1) + EP_X2(ep) = min (nc, x2) + EP_Y1(ep) = max (1, y1) + EP_Y2(ep) = min (nl, y2) + EP_NX(ep) = EP_X2(ep) - EP_X1(ep) + 1 + EP_NY(ep) = EP_Y2(ep) - EP_Y1(ep) + 1 + EP_NPTS(ep) = EP_NX(ep) * EP_NY(ep) + EP_OUTDATA(ep) = imps2r (im, EP_X1(ep), EP_X2(ep), EP_Y1(ep), EP_Y2(ep)) + EP_INDATA(ep) = imgs2r (im, EP_X1(ep), EP_X2(ep), EP_Y1(ep), EP_Y2(ep)) + call amovr (Memr[EP_INDATA(ep)], Memr[EP_OUTDATA(ep)], EP_NPTS(ep)) +end + + +# EP_GINDATA -- Get input image data only with boundary checking. +# A null pointer is returned if entirely out of bounds. + +procedure ep_gindata (ep, x1, x2, y1, y2) + +pointer ep # EPIX pointer +int x1, x2, y1, y2 # Subraster limits + +int nc, nl +pointer im, imgs2r() + +begin + im = EP_IM(ep) + nc = IM_LEN(im,1) + nl = IM_LEN(im,2) + + if (x2 < 1 || x1 >= nc || y2 < 1 || y1 >= nl) { + call eprintf ("Pixel out of bounds\n") + EP_INDATA(ep) = NULL + return + } + + EP_X1(ep) = max (1, x1) + EP_X2(ep) = min (nc, x2) + EP_Y1(ep) = max (1, y1) + EP_Y2(ep) = min (nl, y2) + EP_NX(ep) = EP_X2(ep) - EP_X1(ep) + 1 + EP_NY(ep) = EP_Y2(ep) - EP_Y1(ep) + 1 + EP_NPTS(ep) = EP_NX(ep) * EP_NY(ep) + EP_INDATA(ep) = imgs2r (im, EP_X1(ep), EP_X2(ep), EP_Y1(ep), EP_Y2(ep)) +end diff --git a/pkg/images/tv/imedit/epgsfit.x b/pkg/images/tv/imedit/epgsfit.x new file mode 100644 index 00000000..976af322 --- /dev/null +++ b/pkg/images/tv/imedit/epgsfit.x @@ -0,0 +1,74 @@ +include <math/gsurfit.h> +include "epix.h" + +# EP_GSFIT -- Fit the background annulus. + +procedure ep_gsfit (ep, data, mask, x, y, w, nx, ny, gs) + +pointer ep # EPIX structure +real data[nx,ny] # Data subraster +int mask[nx,ny] # Mask subraster +real x[nx,ny] # X positions +real y[nx,ny] # Y positions +real w[nx,ny] # Weights +int nx, ny # Subraster size +pointer gs # Surface pointer (returned) + +int i, j, n, npts, xo, yo +pointer sp, work +real amedr() + +begin + call smark (sp) + call salloc (work, nx * ny, TY_REAL) + + gs = NULL + npts = nx * ny + + if (EP_XORDER(ep) == 0 || EP_YORDER(ep) == 0) { + n = 0 + do j = 1, ny { + do i = 1, nx { + if (mask[i,j] == 2) { + Memr[work+n] = data[i,j] + n = n + 1 + } + } + } + call amovkr (amedr (Memr[work], n), Memr[work], npts) + xo = 1 + yo = 1 + } else { + call amovr (data, Memr[work], npts) + xo = EP_XORDER(ep) + yo = EP_YORDER(ep) + } + + n = 0 + do j = 1, ny { + do i = 1, nx { + x[i,j] = i + y[i,j] = j + if (mask[i,j] == 2) { + w[i,j] = 1. + n = n + 1 + } else + w[i,j] = 0. + } + } + + if (n > 7) { + repeat { + call gsinit (gs, GS_POLYNOMIAL, xo, yo, YES, + 1., real (nx), 1., real (ny)) + call gsfit (gs, x, y, Memr[work], w, npts, WTS_USER, n) + if (n == OK) + break + xo = max (1, xo - 1) + yo = max (1, yo - 1) + } + } else + call eprintf ("ERROR: Insufficient background points\n") + + call sfree (sp) +end diff --git a/pkg/images/tv/imedit/epimcopy.x b/pkg/images/tv/imedit/epimcopy.x new file mode 100644 index 00000000..cb0094eb --- /dev/null +++ b/pkg/images/tv/imedit/epimcopy.x @@ -0,0 +1,72 @@ +include <imhdr.h> + +# EP_IMCOPY -- Copy an image. Use sequential routines to permit copying +# images of any dimension. Perform pixel i/o in the datatype of the image, +# to avoid unnecessary type conversion. + +procedure ep_imcopy (image1, image2) + +char image1[ARB] # Input image +char image2[ARB] # Output image + +int npix, junk +pointer buf1, buf2, im1, im2 +long v1[IM_MAXDIM], v2[IM_MAXDIM] + +int imgnls(), imgnli(), imgnll(), imgnlr(), imgnld(), imgnlx() +int impnls(), impnli(), impnll(), impnlr(), impnld(), impnlx() +pointer immap() +errchk immap +errchk imgnls, imgnli, imgnll, imgnlr, imgnld, imgnlx +errchk impnls, impnli, impnll, impnlr, impnld, impnlx + +begin + # Map images. + im1 = immap (image1, READ_ONLY, 0) + im2 = immap (image2, NEW_COPY, im1) + + # Setup start vector for sequential reads and writes. + call amovkl (long(1), v1, IM_MAXDIM) + call amovkl (long(1), v2, IM_MAXDIM) + + # Copy the image. + npix = IM_LEN(im1, 1) + switch (IM_PIXTYPE(im1)) { + case TY_SHORT: + while (imgnls (im1, buf1, v1) != EOF) { + junk = impnls (im2, buf2, v2) + call amovs (Mems[buf1], Mems[buf2], npix) + } + case TY_USHORT, TY_INT: + while (imgnli (im1, buf1, v1) != EOF) { + junk = impnli (im2, buf2, v2) + call amovi (Memi[buf1], Memi[buf2], npix) + } + case TY_LONG: + while (imgnll (im1, buf1, v1) != EOF) { + junk = impnll (im2, buf2, v2) + call amovl (Meml[buf1], Meml[buf2], npix) + } + case TY_REAL: + while (imgnlr (im1, buf1, v1) != EOF) { + junk = impnlr (im2, buf2, v2) + call amovr (Memr[buf1], Memr[buf2], npix) + } + case TY_DOUBLE: + while (imgnld (im1, buf1, v1) != EOF) { + junk = impnld (im2, buf2, v2) + call amovd (Memd[buf1], Memd[buf2], npix) + } + case TY_COMPLEX: + while (imgnlx (im1, buf1, v1) != EOF) { + junk = impnlx (im2, buf2, v2) + call amovx (Memx[buf1], Memx[buf2], npix) + } + default: + call error (1, "unknown pixel datatype") + } + + # Unmap the images. + call imunmap (im2) + call imunmap (im1) +end diff --git a/pkg/images/tv/imedit/epinput.x b/pkg/images/tv/imedit/epinput.x new file mode 100644 index 00000000..8b8e9c4d --- /dev/null +++ b/pkg/images/tv/imedit/epinput.x @@ -0,0 +1,55 @@ +include "epix.h" + +# EP_INPUT -- Replace aperture by data from original input image. +# The aperture is first centered. + +procedure ep_input (ep, ap, xa, ya, xb, yb) + +pointer ep # EPIX pointer +int ap # Aperture type +int xa, ya, xb, yb # Aperture coordinates + +int i, x1, x2, y1, y2 +pointer mask, indata, im, immap(), imgs2r() + +begin + i = max (5., abs (EP_SEARCH(ep)) + 1) + x1 = min (xa, xb) - i + x2 = max (xa, xb) + i + y1 = min (ya, yb) - i + y2 = max (ya, yb) + i + call ep_gdata (ep, x1, x2, y1, y2) + if (EP_OUTDATA(ep) != NULL) { + call malloc (mask, EP_NPTS(ep), TY_INT) + + call ep_search (ep, Memr[EP_OUTDATA(ep)], EP_NX(ep), + EP_NY(ep), ap, xa, ya, xb, yb) + call ep_mask (ep, mask, ap, xa, ya, xb, yb) + + im = immap (EP_INPUT(ep), READ_ONLY, 0) + indata = imgs2r (im, EP_X1(ep), EP_X2(ep), EP_Y1(ep), EP_Y2(ep)) + call ep_input1 (Memr[indata], Memi[mask], Memr[EP_OUTDATA(ep)], + EP_NPTS(ep)) + call imunmap (im) + + call mfree (mask, TY_INT) + } +end + + +# EP_INPUT1 -- Replace aperture by input data. + +procedure ep_input1 (indata, mask, outdata, npts) + +real indata[npts] # Data subraster +int mask[npts] # Mask subraster +real outdata[npts] # Input buffer data +int npts # Number of points + +int i + +begin + do i = 1, npts + if (mask[i] == 1) + outdata[i] = indata[i] +end diff --git a/pkg/images/tv/imedit/epix.h b/pkg/images/tv/imedit/epix.h new file mode 100644 index 00000000..d794ac8b --- /dev/null +++ b/pkg/images/tv/imedit/epix.h @@ -0,0 +1,50 @@ +# Parameter data structure + +define EP_SZFNAME 99 # Length of file name +define EP_SZLINE 199 # Length of line +define EP_LEN 379 # Length of EP structure + +define EP_INPUT Memc[P2C($1)] # Input image name +define EP_OUTPUT Memc[P2C($1+50)] # Output image name +define EP_WORK Memc[P2C($1+100)] # Working image name +define EP_SECTION Memc[P2C($1+150)] # Image section +define EP_GRAPHICS Memc[P2C($1+200)] # Graphics device +define EP_COMMAND Memc[P2C($1+250)] # Display command + +define EP_ANGH Memr[P2R($1+350)] # Horizontal viewing angle +define EP_ANGV Memr[P2R($1+351)] # Vertical viewing angle +define EP_APERTURE Memi[$1+352] # Aperture type +define EP_AUTODISPLAY Memi[$1+353] # Automatic image display? +define EP_AUTOSURFACE Memi[$1+354] # Automatic surface plots? +define EP_BUFFER Memr[P2R($1+355)] # Background buffer width +define EP_DEFAULT Memi[$1+356] # Default edit option +define EP_DISPLAY Memi[$1+357] # Display images? +define EP_FIXPIX Memi[$1+358] # Fixpix input? +define EP_RADIUS Memr[P2R($1+359)] # Aperture radius +define EP_SEARCH Memr[P2R($1+360)] # Search radius +define EP_SIGMA Memr[P2R($1+361)] # Added noise sigma +define EP_VALUE Memr[P2R($1+362)] # Substitution value +define EP_MINVALUE Memr[P2R($1+363)] # Minimum value for edit +define EP_MAXVALUE Memr[P2R($1+364)] # Maximum value for edit +define EP_WIDTH Memr[P2R($1+365)] # Background width +define EP_XORDER Memi[$1+366] # Background xorder +define EP_YORDER Memi[$1+367] # Background xorder + +define EP_LOGFD Memi[$1+368] # Log file descriptor +define EP_IM Memi[$1+369] # IMIO pointer +define EP_INDATA Memi[$1+370] # Input data pointer +define EP_OUTDATA Memi[$1+371] # Output data pointer +define EP_NX Memi[$1+372] # Number of columns in subraster +define EP_NY Memi[$1+373] # Number of lines in subraster +define EP_NPTS Memi[$1+374] # Number of pixels in subraster +define EP_X1 Memi[$1+375] # Starting column of subraster +define EP_Y1 Memi[$1+376] # Starting line of subraster +define EP_X2 Memi[$1+377] # Ending column of subraster +define EP_Y2 Memi[$1+378] # Ending line of subraster + +define APTYPES "|circular|square|" # Aperture types +define APRECTANGLE 0 # Rectangular aperture +define APCIRCULAR 1 # Circular aperture +define APSQUARE 2 # Square aperture +define APCDIAG 3 # Diagonal with column interp +define APLDIAG 4 # Diagonal with column interp diff --git a/pkg/images/tv/imedit/epline.x b/pkg/images/tv/imedit/epline.x new file mode 100644 index 00000000..2644beb8 --- /dev/null +++ b/pkg/images/tv/imedit/epline.x @@ -0,0 +1,80 @@ +include "epix.h" + +# EP_LINE -- Replace aperture by line interpolation from background annulus. +# The aperture is first centered. The interpolation is across lines +# from the nearest pixel in the background annulus. Gaussian noise may +# be added. + +procedure ep_line (ep, ap, xa, ya, xb, yb) + +pointer ep # EPIX pointer +int ap # Aperture type +int xa, ya, xb, yb # Aperture coordinates + +int i, x1, x2, y1, y2 +pointer mask, gs + +begin + i = abs (EP_SEARCH(ep)) + EP_BUFFER(ep) + 1 + x1 = min (xa, xb) + x2 = max (xa, xb) + y1 = min (ya, yb) - i + y2 = max (ya, yb) + i + call ep_gdata (ep, x1, x2, y1, y2) + if (EP_OUTDATA(ep) != NULL) { + call malloc (mask, EP_NPTS(ep), TY_INT) + + call ep_search (ep, Memr[EP_OUTDATA(ep)], EP_NX(ep), + EP_NY(ep), ap, xa, ya, xb, yb) + call ep_mask (ep, mask, ap, xa, ya, xb, yb) + call ep_line1 (Memr[EP_OUTDATA(ep)], Memi[mask], + EP_NX(ep), EP_NY(ep)) + if (!IS_INDEF (EP_SIGMA(ep))) + call ep_noise (EP_SIGMA(ep), Memr[EP_OUTDATA(ep)], + Memi[mask], Memr[EP_OUTDATA(ep)], Memr[EP_OUTDATA(ep)], + EP_NPTS(ep), gs) + + call mfree (mask, TY_INT) + } +end + + +# EP_LINE1 -- Interpolate across lines. + +procedure ep_line1 (data, mask, nx, ny) + +real data[nx,ny] # Data subraster +int mask[nx,ny] # Mask subraster +int nx, ny # Number of points + +int i, j, ya, yb, yc, yd +real a, b + +begin + do i = 1, nx { + for (ya=1; ya<=ny && mask[i,ya]!=1; ya=ya+1) + ; + if (ya > ny) + next + for (yb=ny; yb>ya && mask[i,yb]!=1; yb=yb-1) + ; + for (yc=ya; yc>=1 && mask[i,yc]!=2; yc=yc-1) + ; + for (yd=yb; yd<=ny && mask[i,yd]!=2; yd=yd+1) + ; + if (yc < 1 && yd > ny) + next + else if (yc < 1) + do j = ya, yb + data[i,j] = data[i,yd] + else if (yd > ny) + do j = ya, yb + data[i,j] = data[i,yc] + else { + a = data[i,yc] + b = (data[i,yd] - a) / (yd - yc) + do j = ya, yb + data[i,j] = a + b * (j - yc) + } + } +end diff --git a/pkg/images/tv/imedit/epmask.x b/pkg/images/tv/imedit/epmask.x new file mode 100644 index 00000000..12fd8fc9 --- /dev/null +++ b/pkg/images/tv/imedit/epmask.x @@ -0,0 +1,177 @@ +include <mach.h> +include "epix.h" + +# EP_MASK -- Make a mask array with 1=aperture and 2=background annulus. +# +# Exclude values outside a specified range. + +procedure ep_mask (ep, mask, ap, xa, ya, xb, yb) + +pointer ep # EPIX pointer +pointer mask # Mask pointer +int ap # Aperture type +int xa, ya, xb, yb # Aperture + +int xc, yc, i, j +real rad, r, a, b, c, d, minv, maxv +int x1a, x1b, x1c, x2a, x2b, x2c, y1a, y1b, y1c, y2a, y2b, y2c +pointer sp, line, ptr1, ptr2 + +begin + rad = max (0.5, EP_RADIUS(ep)) + + switch (ap) { + case APCIRCULAR: + xc = nint ((xa + xb) / 2.) + yc = nint ((ya + yb) / 2.) + + a = rad ** 2 + b = (rad + EP_BUFFER(ep)) ** 2 + c = (rad + EP_BUFFER(ep) + EP_WIDTH(ep)) ** 2 + + ptr1 = mask + do j = EP_Y1(ep), EP_Y2(ep) { + d = (j - yc) ** 2 + do i = EP_X1(ep), EP_X2(ep) { + r = d + (i - xc) ** 2 + if (r <= a) + Memi[ptr1] = 1 + else if (r >= b && r <= c) + Memi[ptr1] = 2 + else + Memi[ptr1] = 0 + ptr1 = ptr1 + 1 + } + } + case APCDIAG: + a = rad + b = rad + EP_BUFFER(ep) + c = rad + EP_BUFFER(ep) + EP_WIDTH(ep) + + if (yb - ya != 0) + d = real (xb - xa) / (yb - ya) + else + d = 1. + + ptr1 = mask + do j = EP_Y1(ep), EP_Y2(ep) { + xc = xa + d * (j - ya) + do i = EP_X1(ep), EP_X2(ep) { + r = abs (i - xc) + if (r <= a) + Memi[ptr1] = 1 + else if (r >= b && r <= c) + Memi[ptr1] = 2 + else + Memi[ptr1] = 0 + ptr1 = ptr1 + 1 + } + } + case APLDIAG: + a = rad + b = rad + EP_BUFFER(ep) + c = rad + EP_BUFFER(ep) + EP_WIDTH(ep) + + if (xb - xa != 0) + d = real (yb - ya) / (xb - xa) + else + d = 1. + + ptr1 = mask + do j = EP_Y1(ep), EP_Y2(ep) { + do i = EP_X1(ep), EP_X2(ep) { + yc = ya + d * (i - xa) + r = abs (j - yc) + if (r <= a) + Memi[ptr1] = 1 + else if (r >= b && r <= c) + Memi[ptr1] = 2 + else + Memi[ptr1] = 0 + ptr1 = ptr1 + 1 + } + } + default: + call smark (sp) + call salloc (line, EP_NX(ep), TY_INT) + + x1a = max (EP_X1(ep), min (xa, xb)) + x1b = max (EP_X1(ep), int (x1a - EP_BUFFER(ep))) + x1c = max (EP_X1(ep), int (x1a - EP_BUFFER(ep) - EP_WIDTH(ep))) + x2a = min (EP_X2(ep), max (xa, xb)) + x2b = min (EP_X2(ep), int (x2a + EP_BUFFER(ep))) + x2c = min (EP_X2(ep), int (x2a + EP_BUFFER(ep) + EP_WIDTH(ep))) + + y1a = max (EP_Y1(ep), min (ya, yb)) + y1b = max (EP_Y1(ep), int (y1a - EP_BUFFER(ep))) + y1c = max (EP_Y1(ep), int (y1a - EP_BUFFER(ep) - EP_WIDTH(ep))) + y2a = min (EP_Y2(ep), max (ya, yb)) + y2b = min (EP_Y2(ep), int (y2a + EP_BUFFER(ep))) + y2c = min (EP_Y2(ep), int (y2a + EP_BUFFER(ep) + EP_WIDTH(ep))) + + ptr1 = line - EP_X1(ep) + ptr2 = mask - EP_Y1(ep) * EP_NX(ep) + + for (i=EP_X1(ep); i<x1c; i=i+1) + Memi[ptr1+i] = 0 + for (; i<x1b; i=i+1) + Memi[ptr1+i] = 2 + for (; i<x1a; i=i+1) + Memi[ptr1+i] = 0 + for (; i<=x2a; i=i+1) + Memi[ptr1+i] = 1 + for (; i<=x2b; i=i+1) + Memi[ptr1+i] = 0 + for (; i<=x2c; i=i+1) + Memi[ptr1+i] = 2 + for (; i<=EP_X2(ep); i=i+1) + Memi[ptr1+i] = 0 + do i = y1a, y2a + call amovi (Memi[line], Memi[ptr2+i*EP_NX(ep)], EP_NX(ep)) + + for (i=x1a; i<=x2a; i=i+1) + Memi[ptr1+i] = 0 + for (i=y1b; i<y1a; i=i+1) + call amovi (Memi[line], Memi[ptr2+i*EP_NX(ep)], EP_NX(ep)) + for (i=y2a+1; i<=y2b; i=i+1) + call amovi (Memi[line], Memi[ptr2+i*EP_NX(ep)], EP_NX(ep)) + + for (i=x1b; i<=x2b; i=i+1) + Memi[ptr1+i] = 2 + for (i=y1c; i<y1b; i=i+1) + call amovi (Memi[line], Memi[ptr2+i*EP_NX(ep)], EP_NX(ep)) + for (i=y2b+1; i<=y2c; i=i+1) + call amovi (Memi[line], Memi[ptr2+i*EP_NX(ep)], EP_NX(ep)) + + for (i=EP_Y1(ep); i<y1c; i=i+1) + call aclri (Memi[ptr2+i*EP_NX(ep)], EP_NX(ep)) + for (i=y2c+1; i<=EP_Y2(ep); i=i+1) + call aclri (Memi[ptr2+i*EP_NX(ep)], EP_NX(ep)) + + call sfree (sp) + } + + # Exclude data values. + ptr2 = EP_OUTDATA(ep) + if (ptr2 == NULL || + (IS_INDEFR(EP_MINVALUE(ep)) && IS_INDEFR(EP_MAXVALUE(ep)))) + return + + minv = EP_MINVALUE(ep) + maxv = EP_MAXVALUE(ep) + if (IS_INDEFR(minv)) + minv = -MAX_REAL + if (IS_INDEFR(maxv)) + maxv = MAX_REAL + ptr1 = mask + do j = EP_Y1(ep), EP_Y2(ep) { + do i = EP_X1(ep), EP_X2(ep) { + if (Memi[ptr1] != 0) { + if (Memr[ptr2] < minv || Memr[ptr2] > maxv) + Memi[ptr1] = 0 + } + ptr1 = ptr1 + 1 + ptr2 = ptr2 + 1 + } + } +end diff --git a/pkg/images/tv/imedit/epmove.x b/pkg/images/tv/imedit/epmove.x new file mode 100644 index 00000000..687a200e --- /dev/null +++ b/pkg/images/tv/imedit/epmove.x @@ -0,0 +1,129 @@ +include "epix.h" + +# EP_MOVE -- Replace the output aperture by the data in the input aperture. +# There is no centering. A background is fit to the input data and subtracted +# and then a background is fit to the output aperture and added to the +# input aperture data. + +procedure ep_move (ep, ap, xa1, ya1, xb1, yb1, xa2, ya2, xb2, yb2, key) + +pointer ep # EPIX structure +int ap # Aperture type +int xa1, ya1, xb1, yb1 # Aperture coordinates +int xa2, ya2, xb2, yb2 # Aperture coordinates +int key # Key + +int i, x1, x2, y1, y2 +pointer bufdata, mask, x, y, w + +begin + i = EP_BUFFER(ep) + EP_WIDTH(ep) + 1 + x1 = min (xa1, xb1) - i + x2 = max (xa1, xb1) + i + y1 = min (ya1, yb1) - i + y2 = max (ya1, yb1) + i + call ep_gindata (ep, x1, x2, y1, y2) + if (EP_INDATA(ep) != NULL) { + call malloc (bufdata, EP_NPTS(ep), TY_REAL) + call malloc (mask, EP_NPTS(ep), TY_INT) + call malloc (x, EP_NPTS(ep), TY_REAL) + call malloc (y, EP_NPTS(ep), TY_REAL) + call malloc (w, EP_NPTS(ep), TY_REAL) + + call amovr (Memr[EP_INDATA(ep)], Memr[bufdata], EP_NPTS(ep)) + call ep_mask (ep, mask, ap, xa1, ya1, xb1, yb1) + i = EP_BUFFER(ep) + EP_WIDTH(ep) + 1 + x1 = min (xa2, xb2) - i + x2 = max (xa2, xb2) + i + y1 = min (ya2, yb2) - i + y2 = max (ya2, yb2) + i + i = EP_NPTS(ep) + call ep_gdata (ep, x1, x2, y1, y2) + if (i != EP_NPTS(ep)) { + call eprintf ("Raster sizes don't match\n") + EP_OUTDATA(ep) = NULL + } + if (EP_OUTDATA(ep) != NULL) { + switch (key) { + case 'm': + call ep_movem (ep, Memr[bufdata], Memr[EP_OUTDATA(ep)], + Memi[mask], Memr[x], Memr[y], Memr[w], + EP_NX(ep), EP_NY(ep)) + case 'n': + call ep_moven (ep, Memr[bufdata], Memr[EP_OUTDATA(ep)], + Memi[mask], Memr[x], Memr[y], Memr[w], + EP_NX(ep), EP_NY(ep)) + } + } + + call mfree (bufdata, TY_REAL) + call mfree (mask, TY_INT) + call mfree (x, TY_REAL) + call mfree (y, TY_REAL) + call mfree (w, TY_REAL) + } +end + + +# EP_MOVEM -- Move the input aperture to the output. + +procedure ep_movem (ep, indata, outdata, mask, x, y, w, nx, ny) + +pointer ep # EPIX structure +real indata[nx,ny] # Input data subraster +real outdata[nx,ny] # Output data subraster +int mask[nx,ny] # Mask subraster +real x[nx,ny], y[nx,ny] # Coordinates +real w[nx,ny] # Weights +int nx, ny # Size of subraster + +int i, j +real gseval() +pointer gsin, gsout + +begin + call ep_gsfit (ep, indata, mask, x, y, w, nx, ny, gsin) + if (gsin == NULL) + return + call ep_gsfit (ep, outdata, mask, x, y, w, nx, ny, gsout) + if (gsout == NULL) { + call gsfree (gsin) + return + } + do j = 1, ny + do i = 1, nx + if (mask[i,j] == 1) + outdata[i,j] = indata[i,j] - gseval (gsin, x[i,j], y[i,j]) + + gseval (gsout, x[i,j], y[i,j]) + call gsfree (gsin) + call gsfree (gsout) +end + + +# EP_MOVEN -- Add the input aperture to the output. + +procedure ep_moven (ep, indata, outdata, mask, x, y, w, nx, ny) + +pointer ep # EPIX structure +real indata[nx,ny] # Input data subraster +real outdata[nx,ny] # Output data subraster +int mask[nx,ny] # Mask subraster +real x[nx,ny], y[nx,ny] # Coordinates +real w[nx,ny] # Weights +int nx, ny # Size of subraster + +int i, j +real gseval() +pointer gs + +begin + call ep_gsfit (ep, indata, mask, x, y, w, nx, ny, gs) + if (gs == NULL) + return + do j = 1, ny + do i = 1, nx + if (mask[i,j] == 1) + outdata[i,j] = indata[i,j] - gseval (gs, x[i,j], y[i,j]) + + outdata[i,j] + call gsfree (gs) +end diff --git a/pkg/images/tv/imedit/epnoise.x b/pkg/images/tv/imedit/epnoise.x new file mode 100644 index 00000000..796e5038 --- /dev/null +++ b/pkg/images/tv/imedit/epnoise.x @@ -0,0 +1,95 @@ +# EP_NOISE -- Add noise. +# If the sigma is zero add no noise. If a nonzero sigma is given then +# add gaussian random noise. If the sigma is INDEF then use histogram +# sampling from the background. The background histogram is corrected +# for a background function. The histogram is sampled by sorting the +# background values and selecting uniformly from the central 80%. + +procedure ep_noise (sigma, data, mask, x, y, npts, gs) + +real sigma # Noise sigma +real data[npts] # Image data +int mask[npts] # Mask (1=object, 2=background) +real x[npts], y[npts] # Coordinates +int npts # Number of pixels in subraster +pointer gs # Background surface + +int i, j, nbg +real a, b, urand(), gseval(), ep_gauss() +pointer bg + +long seed +data seed /1/ + +begin + # Add gaussian random noise. + if (!IS_INDEF (sigma)) { + if (sigma <= 0.) + return + do i = 1, npts { + if (mask[i] == 1) + data[i] = data[i] + sigma * ep_gauss (seed) + } + return + } + + # Add background sampling with background slope correction. + + if (gs == NULL) + return + + call malloc (bg, npts, TY_REAL) + + nbg = 0 + do i = 1, npts { + if (mask[i] == 2) { + Memr[bg+nbg] = data[i] - gseval (gs, x[i], y[i]) + nbg = nbg + 1 + } + } + if (nbg < 10) { + call mfree (bg, TY_REAL) + return + } + + call asrtr (Memr[bg], Memr[bg], nbg) + a = .1 * nbg - 1 + b = .8 * nbg + + do i = 1, npts + if (mask[i] == 1) { + j = a + b * urand (seed) + data[i] = data[i] + Memr[bg + j] + } + + call mfree (bg, TY_REAL) +end + + +# EP_GAUSS -- Gaussian random number generator based on uniform random number +# generator. + +real procedure ep_gauss (seed) + +long seed # Random number seed + +real a, b, c, d, urand() +int flag +data flag/NO/ + +begin + if (flag == NO) { + repeat { + a = 2. * urand (seed) - 1. + b = 2. * urand (seed) - 1. + c = a * a + b * b + } until (c <= 1.) + + d = sqrt (-2. * log (c) / c) + flag = YES + return (a * d) + } else { + flag = NO + return (b * d) + } +end diff --git a/pkg/images/tv/imedit/epreplace.gx b/pkg/images/tv/imedit/epreplace.gx new file mode 100644 index 00000000..df09e50b --- /dev/null +++ b/pkg/images/tv/imedit/epreplace.gx @@ -0,0 +1,167 @@ +include <mach.h> +include <imhdr.h> +include "epix.h" + + +# EP_REPLACE -- Replace all pixels that are ==, <=, or >= to the value at the +# reference pixel. Since this allocates and gets sections this may result in +# the entire image being put into memory with potential memory problems. It +# is intended for use with masks that have regions of constant values. +# +# Note that this version assumes the pixel values may be ACE object masks. + +$for (ir) +procedure ep_replace$t (ep, x, y, key) + +pointer ep #I EPIX pointer +int x, y #I Reference pixel +int key #I Key + +int i, j, nc, nl, x1, x2, y1, y2 +real minv, maxv +PIXEL val, ival, oval +pointer im, buf + +$if (datatype == i) +int andi() +$endif +pointer imgs2$t(), imps2$t() +errchk imgs2$t, imps2$t + +begin + im = EP_IM(ep) + nc = IM_LEN(im,1) + nl = IM_LEN(im,2) + + EP_INDATA(ep) = NULL + EP_OUTDATA(ep) = NULL + if (x < 1 || x > nc || y < 1 || y > nl) { + call eprintf ("Pixel out of bounds\n") + return + } + + # Get reference pixel value and replacement value. + buf = imgs2$t (im, x, x, y, y) + $if (datatype == i) + ival = andi (Mem$t[buf], 0777777B) + $else + ival = Mem$t[buf] + $endif + oval = EP_VALUE(ep) + minv = EP_MINVALUE(ep) + maxv = EP_MAXVALUE(ep) + if (IS_INDEFR(minv)) + minv = -MAX_REAL + if (IS_INDEFR(maxv)) + minv = MAX_REAL + + # This requires two passes to fit into the subraster model. + # First pass finds the limits of the change and the second + # makes the change. + + x1 = x+1; x2 = x-1; y1 = y+1; y2 = y-1 + do j = 1, nl { + buf = imgs2$t (im, 1, nc, j, j) + switch (key) { + case '=': + do i = 1, nc { + $if (datatype == i) + val = andi (Mem$t[buf+i-1], 0777777B) + $else + val = Mem$t[buf+i-1] + $endif + if (val != ival || val == oval || val < minv || val > maxv) + next + x1 = min (x1, i) + x2 = max (x2, i) + y1 = min (y1, j) + y2 = max (y2, j) + } + case '<': + do i = 1, nc { + $if (datatype == i) + val = andi (Mem$t[buf+i-1], 0777777B) + $else + val = Mem$t[buf+i-1] + $endif + if (val > ival || val == oval || val < minv || val > maxv) + next + x1 = min (x1, i) + x2 = max (x2, i) + y1 = min (y1, j) + y2 = max (y2, j) + } + case '>': + do i = 1, nc { + $if (datatype == i) + val = andi (Mem$t[buf+i-1], 0777777B) + $else + val = Mem$t[buf+i-1] + $endif + if (val < ival || val == oval || val < minv || val > maxv) + next + x1 = min (x1, i) + x2 = max (x2, i) + y1 = min (y1, j) + y2 = max (y2, j) + } + } + } + + # No pixels to change. + if (x2 < x1 || y2 < y1) + return + + # Set the rasters and change the pixels. + EP_X1(ep) = x1 + EP_X2(ep) = x2 + EP_Y1(ep) = y1 + EP_Y2(ep) = y2 + EP_NX(ep) = EP_X2(ep) - EP_X1(ep) + 1 + EP_NY(ep) = EP_Y2(ep) - EP_Y1(ep) + 1 + EP_NPTS(ep) = EP_NX(ep) * EP_NY(ep) + + EP_OUTDATA(ep) = imps2$t (im, EP_X1(ep), EP_X2(ep), EP_Y1(ep), + EP_Y2(ep)) + EP_INDATA(ep) = imgs2$t (im, EP_X1(ep), EP_X2(ep), EP_Y1(ep), + EP_Y2(ep)) + + buf = EP_OUTDATA(ep) + call amov$t (Mem$t[EP_INDATA(ep)], Mem$t[buf], EP_NPTS(ep)) + switch (key) { + case '=': + do i = 1, EP_NPTS(ep) { + $if (datatype == i) + val = andi (Mem$t[buf], 0777777B) + $else + val = Mem$t[buf] + $endif + if (val == ival && val >= minv && val <= maxv) + Mem$t[buf] = oval + buf = buf + 1 + } + case '<': + do i = 1, EP_NPTS(ep) { + $if (datatype == i) + val = andi (Mem$t[buf], 0777777B) + $else + val = Mem$t[buf] + $endif + if (val <= ival && val >= minv && val <= maxv) + Mem$t[buf] = oval + buf = buf + 1 + } + case '>': + do i = 1, EP_NPTS(ep) { + $if (datatype == i) + val = andi (Mem$t[buf], 0777777B) + $else + val = Mem$t[buf] + $endif + if (val >= ival && val >= minv && val <= maxv) + Mem$t[buf] = oval + buf = buf + 1 + } + } +end +$endfor diff --git a/pkg/images/tv/imedit/epreplace.x b/pkg/images/tv/imedit/epreplace.x new file mode 100644 index 00000000..c79b943f --- /dev/null +++ b/pkg/images/tv/imedit/epreplace.x @@ -0,0 +1,260 @@ +include <mach.h> +include <imhdr.h> +include "epix.h" + + +# EP_REPLACE -- Replace all pixels that are ==, <=, or >= to the value at the +# reference pixel. Since this allocates and gets sections this may result in +# the entire image being put into memory with potential memory problems. It +# is intended for use with masks that have regions of constant values. +# +# Note that this version assumes the pixel values may be ACE object masks. + + +procedure ep_replacei (ep, x, y, key) + +pointer ep #I EPIX pointer +int x, y #I Reference pixel +int key #I Key + +int i, j, nc, nl, x1, x2, y1, y2 +real minv, maxv +int val, ival, oval +pointer im, buf + +int andi() +pointer imgs2i(), imps2i() +errchk imgs2i, imps2i + +begin + im = EP_IM(ep) + nc = IM_LEN(im,1) + nl = IM_LEN(im,2) + + EP_INDATA(ep) = NULL + EP_OUTDATA(ep) = NULL + if (x < 1 || x > nc || y < 1 || y > nl) { + call eprintf ("Pixel out of bounds\n") + return + } + + # Get reference pixel value and replacement value. + buf = imgs2i (im, x, x, y, y) + ival = andi (Memi[buf], 0777777B) + oval = EP_VALUE(ep) + minv = EP_MINVALUE(ep) + maxv = EP_MAXVALUE(ep) + if (IS_INDEFR(minv)) + minv = -MAX_REAL + if (IS_INDEFR(maxv)) + minv = MAX_REAL + + # This requires two passes to fit into the subraster model. + # First pass finds the limits of the change and the second + # makes the change. + + x1 = x+1; x2 = x-1; y1 = y+1; y2 = y-1 + do j = 1, nl { + buf = imgs2i (im, 1, nc, j, j) + switch (key) { + case '=': + do i = 1, nc { + val = andi (Memi[buf+i-1], 0777777B) + if (val != ival || val == oval || val < minv || val > maxv) + next + x1 = min (x1, i) + x2 = max (x2, i) + y1 = min (y1, j) + y2 = max (y2, j) + } + case '<': + do i = 1, nc { + val = andi (Memi[buf+i-1], 0777777B) + if (val > ival || val == oval || val < minv || val > maxv) + next + x1 = min (x1, i) + x2 = max (x2, i) + y1 = min (y1, j) + y2 = max (y2, j) + } + case '>': + do i = 1, nc { + val = andi (Memi[buf+i-1], 0777777B) + if (val < ival || val == oval || val < minv || val > maxv) + next + x1 = min (x1, i) + x2 = max (x2, i) + y1 = min (y1, j) + y2 = max (y2, j) + } + } + } + + # No pixels to change. + if (x2 < x1 || y2 < y1) + return + + # Set the rasters and change the pixels. + EP_X1(ep) = x1 + EP_X2(ep) = x2 + EP_Y1(ep) = y1 + EP_Y2(ep) = y2 + EP_NX(ep) = EP_X2(ep) - EP_X1(ep) + 1 + EP_NY(ep) = EP_Y2(ep) - EP_Y1(ep) + 1 + EP_NPTS(ep) = EP_NX(ep) * EP_NY(ep) + + EP_OUTDATA(ep) = imps2i (im, EP_X1(ep), EP_X2(ep), EP_Y1(ep), + EP_Y2(ep)) + EP_INDATA(ep) = imgs2i (im, EP_X1(ep), EP_X2(ep), EP_Y1(ep), + EP_Y2(ep)) + + buf = EP_OUTDATA(ep) + call amovi (Memi[EP_INDATA(ep)], Memi[buf], EP_NPTS(ep)) + switch (key) { + case '=': + do i = 1, EP_NPTS(ep) { + val = andi (Memi[buf], 0777777B) + if (val == ival && val >= minv && val <= maxv) + Memi[buf] = oval + buf = buf + 1 + } + case '<': + do i = 1, EP_NPTS(ep) { + val = andi (Memi[buf], 0777777B) + if (val <= ival && val >= minv && val <= maxv) + Memi[buf] = oval + buf = buf + 1 + } + case '>': + do i = 1, EP_NPTS(ep) { + val = andi (Memi[buf], 0777777B) + if (val >= ival && val >= minv && val <= maxv) + Memi[buf] = oval + buf = buf + 1 + } + } +end + +procedure ep_replacer (ep, x, y, key) + +pointer ep #I EPIX pointer +int x, y #I Reference pixel +int key #I Key + +int i, j, nc, nl, x1, x2, y1, y2 +real minv, maxv +real val, ival, oval +pointer im, buf + +pointer imgs2r(), imps2r() +errchk imgs2r, imps2r + +begin + im = EP_IM(ep) + nc = IM_LEN(im,1) + nl = IM_LEN(im,2) + + EP_INDATA(ep) = NULL + EP_OUTDATA(ep) = NULL + if (x < 1 || x > nc || y < 1 || y > nl) { + call eprintf ("Pixel out of bounds\n") + return + } + + # Get reference pixel value and replacement value. + buf = imgs2r (im, x, x, y, y) + ival = Memr[buf] + oval = EP_VALUE(ep) + minv = EP_MINVALUE(ep) + maxv = EP_MAXVALUE(ep) + if (IS_INDEFR(minv)) + minv = -MAX_REAL + if (IS_INDEFR(maxv)) + minv = MAX_REAL + + # This requires two passes to fit into the subraster model. + # First pass finds the limits of the change and the second + # makes the change. + + x1 = x+1; x2 = x-1; y1 = y+1; y2 = y-1 + do j = 1, nl { + buf = imgs2r (im, 1, nc, j, j) + switch (key) { + case '=': + do i = 1, nc { + val = Memr[buf+i-1] + if (val != ival || val == oval || val < minv || val > maxv) + next + x1 = min (x1, i) + x2 = max (x2, i) + y1 = min (y1, j) + y2 = max (y2, j) + } + case '<': + do i = 1, nc { + val = Memr[buf+i-1] + if (val > ival || val == oval || val < minv || val > maxv) + next + x1 = min (x1, i) + x2 = max (x2, i) + y1 = min (y1, j) + y2 = max (y2, j) + } + case '>': + do i = 1, nc { + val = Memr[buf+i-1] + if (val < ival || val == oval || val < minv || val > maxv) + next + x1 = min (x1, i) + x2 = max (x2, i) + y1 = min (y1, j) + y2 = max (y2, j) + } + } + } + + # No pixels to change. + if (x2 < x1 || y2 < y1) + return + + # Set the rasters and change the pixels. + EP_X1(ep) = x1 + EP_X2(ep) = x2 + EP_Y1(ep) = y1 + EP_Y2(ep) = y2 + EP_NX(ep) = EP_X2(ep) - EP_X1(ep) + 1 + EP_NY(ep) = EP_Y2(ep) - EP_Y1(ep) + 1 + EP_NPTS(ep) = EP_NX(ep) * EP_NY(ep) + + EP_OUTDATA(ep) = imps2r (im, EP_X1(ep), EP_X2(ep), EP_Y1(ep), + EP_Y2(ep)) + EP_INDATA(ep) = imgs2r (im, EP_X1(ep), EP_X2(ep), EP_Y1(ep), + EP_Y2(ep)) + + buf = EP_OUTDATA(ep) + call amovr (Memr[EP_INDATA(ep)], Memr[buf], EP_NPTS(ep)) + switch (key) { + case '=': + do i = 1, EP_NPTS(ep) { + val = Memr[buf] + if (val == ival && val >= minv && val <= maxv) + Memr[buf] = oval + buf = buf + 1 + } + case '<': + do i = 1, EP_NPTS(ep) { + val = Memr[buf] + if (val <= ival && val >= minv && val <= maxv) + Memr[buf] = oval + buf = buf + 1 + } + case '>': + do i = 1, EP_NPTS(ep) { + val = Memr[buf] + if (val >= ival && val >= minv && val <= maxv) + Memr[buf] = oval + buf = buf + 1 + } + } +end + diff --git a/pkg/images/tv/imedit/epsearch.x b/pkg/images/tv/imedit/epsearch.x new file mode 100644 index 00000000..814d9a3b --- /dev/null +++ b/pkg/images/tv/imedit/epsearch.x @@ -0,0 +1,90 @@ +include <mach.h> +include "epix.h" + +# EP_SEARCH -- Search input data for maximum or minimum pixel in search radius. +# Return the new aperture positions. The magnitude of the search radius +# defines the range to be searched (bounded by the raster dimension) and +# the sign of the radius determines whether a minimum or maximum is sought. + +procedure ep_search (ep, data, nx, ny, ap, xa, ya, xb, yb) + +pointer ep # EPIX pointer +real data[nx,ny] # Subraster +int nx, ny # Subraster size +int ap # Aperture type +int xa, ya, xb, yb # Aperture (initial and final) + +real xc, yc, search2, dj2, r2, dmax +int i, j, i1, i2, j1, j2, imax, jmax + +begin + if (EP_SEARCH(ep) == 0.) + return + + search2 = abs (EP_SEARCH(ep)) + + xa = xa - EP_X1(ep) + 1 + xb = xb - EP_X1(ep) + 1 + xc = (xa + xb) / 2. + i1 = max (1., xc - search2) + i2 = min (real(nx), xc + search2) + imax = nint (xc) + + ya = ya - EP_Y1(ep) + 1 + yb = yb - EP_Y1(ep) + 1 + yc = (ya + yb) / 2. + j1 = max (1., yc - search2) + j2 = min (real(ny), yc + search2) + jmax = nint (yc) + + dmax = data[imax,jmax] + switch (ap) { + case 1: + search2 = EP_SEARCH(ep) ** 2 + do j = j1, j2 { + dj2 = (j - yc) ** 2 + do i = i1, i2 { + r2 = dj2 + (i - xc) ** 2 + if (r2 > search2) + next + + if (EP_SEARCH(ep) > 0.) { + if (data[i,j] > dmax) { + dmax = data[i,j] + imax = i + jmax = j + } + } else { + if (data[i,j] < dmax) { + dmax = data[i,j] + imax = i + jmax = j + } + } + } + } + default: + do j = j1, j2 { + do i = i1, i2 { + if (EP_SEARCH(ep) > 0.) { + if (data[i,j] > dmax) { + dmax = data[i,j] + imax = i + jmax = j + } + } else { + if (data[i,j] < dmax) { + dmax = data[i,j] + imax = i + jmax = j + } + } + } + } + } + + xa = xa + (imax - xc) + EP_X1(ep) - 1 + xb = xb + (imax - xc) + EP_X1(ep) - 1 + ya = ya + (jmax - yc) + EP_Y1(ep) - 1 + yb = yb + (jmax - yc) + EP_Y1(ep) - 1 +end diff --git a/pkg/images/tv/imedit/epsetpars.x b/pkg/images/tv/imedit/epsetpars.x new file mode 100644 index 00000000..4101ff5a --- /dev/null +++ b/pkg/images/tv/imedit/epsetpars.x @@ -0,0 +1,75 @@ +include <error.h> +include "epix.h" + +# EP_SETPARS -- Set the parameter values in the EPIX structure. +# If a logfile is given record selected parameters. + +procedure ep_setpars (ep) + +pointer ep # EPIX structure + +int fd, clgeti(), btoi(), clgwrd(), nowhite(), open() +char clgetc() +bool clgetb() +real clgetr() +pointer sp, aperture, logfile +errchk open + +begin + call smark (sp) + call salloc (aperture, SZ_FNAME, TY_CHAR) + call salloc (logfile, SZ_FNAME, TY_CHAR) + + EP_ANGH(ep) = clgetr ("angh") + EP_ANGV(ep) = clgetr ("angv") + EP_APERTURE(ep) = clgwrd ("aperture", Memc[aperture], SZ_FNAME, APTYPES) + EP_AUTODISPLAY(ep) = btoi (clgetb ("autodisplay")) + EP_AUTOSURFACE(ep) = btoi (clgetb ("autosurface")) + EP_BUFFER(ep) = clgetr ("buffer") + EP_DEFAULT(ep) = clgetc ("default") + EP_DISPLAY(ep) = btoi (clgetb ("display")) + EP_FIXPIX(ep) = btoi (clgetb ("fixpix")) + EP_RADIUS(ep) = clgetr ("radius") + EP_SEARCH(ep) = clgetr ("search") + EP_SIGMA(ep) = clgetr ("sigma") + EP_VALUE(ep) = clgetr ("value") + EP_MINVALUE(ep) = clgetr ("minvalue") + EP_MAXVALUE(ep) = clgetr ("maxvalue") + EP_WIDTH(ep) = clgetr ("width") + EP_XORDER(ep) = clgeti ("xorder") + EP_YORDER(ep) = clgeti ("yorder") + call clgstr ("command", EP_COMMAND(ep), EP_SZLINE) + call clgstr ("graphics", EP_GRAPHICS(ep), EP_SZFNAME) + + if (EP_LOGFD(ep) != NULL) + call close (EP_LOGFD(ep)) + EP_LOGFD(ep) = NULL + call clgstr ("logfile", Memc[logfile], SZ_FNAME) + if (nowhite (Memc[logfile], Memc[logfile], SZ_FNAME) > 0) { + iferr { + EP_LOGFD(ep) = open (Memc[logfile], APPEND, TEXT_FILE) + fd = EP_LOGFD(ep) + call fprintf (fd, ":aperture %s\n") + call pargstr (Memc[aperture]) + call fprintf (fd, ":search %g\n") + call pargr (EP_SEARCH(ep)) + call fprintf (fd, ":radius %g\n") + call pargr (EP_RADIUS(ep)) + call fprintf (fd, ":buffer %g\n") + call pargr (EP_BUFFER(ep)) + call fprintf (fd, ":width %g\n") + call pargr (EP_WIDTH(ep)) + call fprintf (fd, ":value %g\n") + call pargr (EP_VALUE(ep)) + call fprintf (fd, ":sigma %g\n") + call pargr (EP_SIGMA(ep)) + call fprintf (fd, ":xorder %d\n") + call pargi (EP_XORDER(ep)) + call fprintf (fd, ":yorder %d\n") + call pargi (EP_YORDER(ep)) + } then + call erract (EA_WARN) + } + + call sfree (sp) +end diff --git a/pkg/images/tv/imedit/epstatistics.x b/pkg/images/tv/imedit/epstatistics.x new file mode 100644 index 00000000..c7f075ea --- /dev/null +++ b/pkg/images/tv/imedit/epstatistics.x @@ -0,0 +1,147 @@ +include "epix.h" + +# EP_STATISTICS -- Compute and print statistics for the input aperture. + +procedure ep_statistics (ep, ap, xa, ya, xb, yb, box) + +pointer ep # EPIX structure +int ap # Aperture type +int xa, ya, xb, yb # Aperture coordinates +int box # Print box? + +int i, x1, x2, y1, y2 +pointer mask, x, y, w, gs + +begin + i = max (5., abs (EP_SEARCH(ep))+EP_BUFFER(ep)+EP_WIDTH(ep)+1) + x1 = min (xa, xb) - i + x2 = max (xa, xb) + i + y1 = min (ya, xb) - i + y2 = max (ya, yb) + i + EP_OUTDATA(ep) = NULL + call ep_gindata (ep, x1, x2, y1, y2) + if (EP_INDATA(ep) != NULL) { + call malloc (mask, EP_NPTS(ep), TY_INT) + call malloc (x, EP_NPTS(ep), TY_REAL) + call malloc (y, EP_NPTS(ep), TY_REAL) + call malloc (w, EP_NPTS(ep), TY_REAL) + + call ep_search (ep, Memr[EP_INDATA(ep)], EP_NX(ep), + EP_NY(ep), ap, xa, ya, xb, yb) + call ep_mask (ep, mask, ap, xa, ya, xb, yb) + call ep_gsfit (ep, Memr[EP_INDATA(ep)], Memi[mask], + Memr[x], Memr[y], Memr[w], EP_NX(ep), EP_NY(ep), gs) + call ep_statistics1 (Memr[EP_INDATA(ep)], Memi[mask], + EP_NX(ep), EP_NY(ep), EP_X1(ep), EP_Y1(ep), + (xa+xb)/2, (ya+yb)/2, gs) + if (box == YES) + call ep_box (Memr[EP_INDATA(ep)], EP_NX(ep), EP_NY(ep), + EP_X1(ep), EP_Y1(ep), xa, ya, xb, yb) + + call mfree (mask, TY_INT) + call mfree (x, TY_REAL) + call mfree (y, TY_REAL) + call mfree (w, TY_REAL) + call gsfree (gs) + } +end + + +# EP_STATISTICS1 -- Compute and print statistics. + +procedure ep_statistics1 (data, mask, nx, ny, x1, y1, x, y, gs) + +real data[nx,ny] # Input data subraster +int mask[nx,ny] # Mask subraster +int nx, ny # Size of subraster +int x1, y1 # Origin of subraster +int x, y # Center of object +pointer gs # GSURFIT pointer + +int i, j, area, nsky +real flux, sky, sigma, d, gseval() + +begin + flux = 0. + area = 0 + sky = 0. + sigma = 0. + nsky = 0 + + do j = 1, ny { + do i = 1, nx { + if (mask[i,j] == 1) { + d = data[i,j] + if (gs != NULL) + d = d - gseval (gs, real (i), real (j)) + flux = flux + d + area = area + 1 + } else if (mask[i,j] == 2) { + d = data[i,j] - gseval (gs, real (i), real (j)) + sky = sky + data[i,j] + sigma = sigma + d * d + nsky = nsky + 1 + } + } + } + + call printf ("x=%d y=%d z=%d mean=%g area=%d") + call pargi (x) + call pargi (y) + call pargr (data[x-x1+1,y-y1+1]) + call pargr (flux / area) + call pargi (area) + + if (nsky > 0) { + call printf (" sky=%g sigma=%g nsky=%d") + call pargr (sky / nsky) + call pargr (sqrt (sigma / nsky)) + call pargi (nsky) + } + + call printf ("\n") +end + + +# EP_BOX -- Print box of pixel values. + +procedure ep_box (data, nx, ny, xo, yo, xa, ya, xb, yb) + +real data[nx,ny] # Input data subraster +int nx, ny # Size of subraster +int xo, yo # Origin of subraster +int xa, ya, xb, yb # Aperture + +int i, j, x1, x2, y1, y2, x, y + +begin + x1 = min (xa, xb) + x2 = max (xa, xb) + y1 = min (ya, yb) + y2 = max (ya, yb) + if (x2 - x1 + 1 <= 10) { + x1 = max (xo, x1 - 1) + x2 = min (xo + nx - 1, x2 + 1) + } + y1 = max (yo, y1 - 1) + y2 = min (yo + ny - 1, y2 + 1) + + call printf ("%4w") + do x = x1, x2 { + call printf (" %4d ") + call pargi (x) + } + call printf ("\n") + + do y = y2, y1, -1 { + call printf ("%4d") + call pargi (y) + j = y - yo + 1 + do x = x1, x2 { + i = x - xo + 1 + call printf (" %5g") + call pargr (data[i,j]) + } + call printf ("\n") + } +end diff --git a/pkg/images/tv/imedit/epsurface.x b/pkg/images/tv/imedit/epsurface.x new file mode 100644 index 00000000..289c814f --- /dev/null +++ b/pkg/images/tv/imedit/epsurface.x @@ -0,0 +1,46 @@ +define DUMMY 6 + +# EP_SURFACE -- Draw a perspective view of a surface. The altitude +# and azimuth of the viewing angle are variable. + +procedure ep_surface(gp, data, ncols, nlines, angh, angv) + +pointer gp # GIO pointer +real data[ncols,nlines] # Surface data to be plotted +int ncols, nlines # Dimensions of surface +real angh, angv # Orientation of surface (degrees) + +int wkid +pointer sp, work + +int first +real vpx1, vpx2, vpy1, vpy2 +common /frstfg/ first +common /noaovp/ vpx1, vpx2, vpy1, vpy2 + +begin + call smark (sp) + call salloc (work, 2 * (2 * ncols * nlines + ncols + nlines), TY_REAL) + + # Initialize surface common blocks + first = 1 + call srfabd() + + # Define viewport. + call ggview (gp, vpx1, vpx2, vpy1, vpy2) + + # Link GKS to GIO + wkid = 1 + call gopks (STDERR) + call gopwk (wkid, DUMMY, gp) + call gacwk (wkid) + + call ezsrfc (data, ncols, nlines, angh, angv, Memr[work]) + + call gdawk (wkid) + # We don't want to close the GIO pointer. + #call gclwk (wkid) + call gclks () + + call sfree (sp) +end diff --git a/pkg/images/tv/imedit/imedit.key b/pkg/images/tv/imedit/imedit.key new file mode 100644 index 00000000..211ad94c --- /dev/null +++ b/pkg/images/tv/imedit/imedit.key @@ -0,0 +1,84 @@ + IMEDIT CURSOR KEYSTROKE COMMANDS + + ? Print help + : Colon commands (see below) + <space> Statistics + g Surface graph + i Initialize (start over without saving changes) + q Quit and save changes + p Print box of pixel values and statistics + r Redraw image display + s Surface plot at cursor + t Toggle between minimum and maximum search + + Increase radius by one + - Decrease radius by one + I Interrupt task immediately + Q Quit without saving changes + +The following editing options are available. Rectangular and line regions +are specified with two positions and aperture regions are specified by +one position. The current aperture type (circular or square) is used +in the latter case. The move option takes two positions, the position +to move from and the position to move to. + + a Background replacement (rectangle) + b Background replacement (aperture) + c Column interpolation (rectangle) + d Constant value substitution (rectangle) + e Constant value substitution (aperture) + f Interpolation across line (line) + j Replace with input data (rectangle) + k Replace with input data (aperture) + l Line interpolation (rectangle) + m Copy by replacement (aperture) + n Copy by addition (aperture) + u Undo last change (see also 'i', 'j', and 'k') + v Constant value substitution (vector) + = Constant value substitution of pixels equal + to pixel at the cursor position + < Constant value substitution of pixels less than or equal + to pixel at the cursor position + > Constant value substitution of pixels greater than or equal + to pixel at the cursor position + +When the image display provides a fill option then the effect of zoom +and roam is provided by loading image sections. This is a temporary +mechanism which will eventually be replaced by a more sophisticated +image display interface. + + E Exapnd image display + P Pan image display + R Redraw image display + Z Zoom image display + 0 Redraw image display with no zoom + 1-9 Shift display + + + IMEDIT COLON COMMANDS + +The colon either print the current value of a parameter when there is +no value or set the parameter to the specified value. + +angh [value] Horizontal viewing angle (degrees) for surface plots +angv [value] Vertical viewing angle (degrees) for surface plots +aperture [type] Aperture type (circular|square) +autodisplay [yes|no] Automatic image display? +autosurface [yes|no] Automatic surface plots? +buffer [value] Background buffer width +command [string] Display command +display [yes|no] Display image? +eparam Edit parameters +graphics [device] Graphics device +input [image] New input image to edit (output is same as input) +output [image] New output image name +radius [value] Aperture radius +search [value] Search radius +sigma [value] Noise sigma (INDEF for histrogram replacement) +value [value] Constant substitution value +minvalue [value] Minimum value for modification (INDEF=minimum) +maxvalue [value] Maximum value for modification (INDEF=maximum) +width [value] Background annulus width +write [name] Write changes to name (default current output name) +xorder [value] X order for background fitting +yorder [value] Y order for background fitting + diff --git a/pkg/images/tv/imedit/mkpkg b/pkg/images/tv/imedit/mkpkg new file mode 100644 index 00000000..438a8752 --- /dev/null +++ b/pkg/images/tv/imedit/mkpkg @@ -0,0 +1,38 @@ +# IMEDIT + +$checkout libpkg.a ../ +$update libpkg.a +$checkin libpkg.a ../ +$exit + +generic: + $ifolder (epreplace.x, epreplace.gx) + $generic -k epreplace.gx -o epreplace.x + $endif + ; + +libpkg.a: + $ifeq (USE_GENERIC, yes) $call generic $endif + + epbackground.x epix.h + epcol.x epix.h + epcolon.x epix.h + epconstant.x epix.h + epdisplay.x epix.h <imhdr.h> + epdosurface.x epix.h + epgcur.x epix.h + epgdata.x epix.h <imhdr.h> + epgsfit.x epix.h <math/gsurfit.h> + epimcopy.x <imhdr.h> + epinput.x epix.h + epline.x epix.h + epmask.x epix.h + epmove.x epix.h + epnoise.x + epreplace.x epix.h <imhdr.h> + epsearch.x epix.h <mach.h> + epsetpars.x epix.h <error.h> + epstatistics.x epix.h + epsurface.x + t_imedit.x epix.h <error.h> <imhdr.h> + ; diff --git a/pkg/images/tv/imedit/t_imedit.x b/pkg/images/tv/imedit/t_imedit.x new file mode 100644 index 00000000..984ce86b --- /dev/null +++ b/pkg/images/tv/imedit/t_imedit.x @@ -0,0 +1,305 @@ +include <error.h> +include <imhdr.h> +include "epix.h" + +define HELP "imedit_help$" +define PROMPT "imedit options" + +# T_IMEDIT -- Edit image pixels. +# This task provides selection of pixels to be edit via cursor or file +# input. The regions to be edited may be defined as a rectangle or a +# center and radius for a circular or square aperture. The replacement +# options include constant substitution, background substitution, column +# or line interpolation, and moving one region to another. In addition +# this task can be used to select and display regions in surface perspective +# and to print statistics. The image display interface temporarily +# used simple calls to a user specified display task (such as TV.DISPLAY). +# The editing is done in a temporary image buffer. The commands which +# alter the input image may be logged if a log file is given. + +procedure t_imedit () + +int inlist # List of input images +int outlist # List of output images + +int i, key, ap, xa, ya, xb, yb, x1, x2, y1, y2 +int change, changes, newdisplay, newimage +bool erase +pointer sp, ep, cmd, temp +pointer im + +bool streq() +pointer immap(), imgl2r(), impl2r() +int imtopenp(), imtlen(), imtgetim(), imaccess(), ep_gcur() +errchk immap, imdelete, ep_imcopy, ep_setpars, imgl2r, impl2r + +define newim_ 99 + +begin + call smark (sp) + call salloc (cmd, SZ_LINE, TY_CHAR) + + # Allocate and initialize imedit descriptor. + call salloc (ep, EP_LEN, TY_STRUCT) + call aclri (Memi[ep], EP_LEN) + + # Check the input and output image lists have proper format. + inlist = imtopenp ("input") + outlist = imtopenp ("output") + if (imtlen (outlist) > 0 && imtlen (outlist) != imtlen (inlist)) + call error (1, "Input and output lists are not the same length") + + # Set the rest of the task parameters. + call ep_setpars (ep) + + # Repeat on each input image. + while (imtgetim (inlist, EP_INPUT(ep), EP_SZFNAME) != EOF) { + if (imtgetim (outlist, EP_OUTPUT(ep), EP_SZFNAME) == EOF) + call strcpy (EP_INPUT(ep), EP_OUTPUT(ep), EP_SZFNAME) + else if (imaccess (EP_OUTPUT(ep), READ_ONLY) == YES) { + call eprintf ("%s: Output image %s exists\n") + call pargstr (EP_INPUT(ep)) + call pargstr (EP_OUTPUT(ep)) + next + } + + # The editing takes place in a temporary editing image buffer. +newim_ call strcpy (EP_OUTPUT(ep), EP_WORK(ep), EP_SZFNAME) + call xt_mkimtemp (EP_OUTPUT(ep), EP_WORK(ep), EP_OUTPUT(ep), + EP_SZFNAME) + iferr (call ep_imcopy (EP_INPUT(ep), EP_WORK(ep))) { + call erract (EA_WARN) + next + } + + EP_IM(ep) = immap (EP_WORK(ep), READ_WRITE, 0) + EP_INDATA(ep) = NULL + EP_OUTDATA(ep) = NULL + + if (EP_LOGFD(ep) != NULL) { + call fprintf (EP_LOGFD(ep), "# Input image %s\n") + call pargstr (EP_INPUT(ep)) + } + + if (EP_DISPLAY(ep) == YES) { + key = '0' + call ep_zoom (ep, xa, ya, xb, yb, key, erase) + call ep_command (ep, EP_WORK(ep), erase) + } + + + # Enter the cursor loop. The apertures and commands are + # returned by the EP_GCUR procedure. + + newimage = NO + changes = 0 + while (ep_gcur (ep,ap,xa,ya,xb,yb,key,Memc[cmd],SZ_LINE) != EOF) { + newdisplay = NO + change = NO + + iferr { + switch (key) { + case '?': # Print help + call pagefile (HELP, PROMPT) + case ':': # Process colon commands + call ep_colon (ep, Memc[cmd], newimage) + if (newimage == YES) + break + case 'a', 'b': # Background replacement + call ep_background (ep, ap, xa, ya, xb, yb) + if (EP_OUTDATA(ep) != NULL) { + change = YES + changes = changes + 1 + } + case 'c': # Column interpolation + call ep_col (ep, ap, xa, ya, xb, yb) + if (EP_OUTDATA(ep) != NULL) { + change = YES + changes = changes + 1 + } + case 'd', 'e', 'v': # Constant value + call ep_constant (ep, ap, xa, ya, xb, yb) + if (EP_OUTDATA(ep) != NULL) { + change = YES + changes = changes + 1 + } + case 'f': # Diagonal aperture + if (ap == APCDIAG) + call ep_col (ep, ap, xa, ya, xb, yb) + else + call ep_line (ep, ap, xa, ya, xb, yb) + if (EP_OUTDATA(ep) != NULL) { + change = YES + changes = changes + 1 + } + case '=', '<', '>': # Replace + if (IM_PIXTYPE(EP_IM(ep)) == TY_INT) + call ep_replacei (ep, xa, ya, key) + else + call ep_replacer (ep, xa, ya, key) + if (EP_OUTDATA(ep) != NULL) { + change = YES + changes = changes + 1 + } + case 'i': # Initialize + call imunmap (EP_IM(ep)) + goto newim_ + case 'j', 'k': # Replace with input + call ep_input (ep, ap, xa, ya, xb, yb) + if (EP_OUTDATA(ep) != NULL) { + change = YES + changes = changes + 1 + } + case 'l': # Line interpolation + call ep_line (ep, ap, xa, ya, xb, yb) + if (EP_OUTDATA(ep) != NULL) { + change = YES + changes = changes + 1 + } + case 'm', 'n': # Move + i = ep_gcur (ep, ap, x1, y1, x2, y2, key, + Memc[cmd],SZ_LINE) + call ep_move (ep, ap, xa, ya, xb, yb, x1, y1, x2, y2, + key) + if (EP_OUTDATA(ep) != NULL) { + change = YES + changes = changes + 1 + } + case 'g': # Surface graph + call ep_dosurface (ep) + case ' ': # Statistics + call ep_statistics (ep, ap, xa, ya, xb, yb, NO) + case 'p': + call ep_statistics (ep, ap, xa, ya, xb, yb, YES) + case 't': + EP_SEARCH(ep) = -EP_SEARCH(ep) + call ep_colon (ep, "search", newimage) + case '+': + EP_RADIUS(ep) = EP_RADIUS(ep) + 1. + call ep_colon (ep, "radius", newimage) + case '-': + EP_RADIUS(ep) = max (0., EP_RADIUS(ep) - 1.) + call ep_colon (ep, "radius", newimage) + case 's': # Surface plot + i = max (5., + abs (EP_SEARCH(ep))+EP_BUFFER(ep)+EP_WIDTH(ep)+1) + x1 = min (xa, xb) - i + x2 = max (xa, xb) + i + y1 = min (ya, yb) - i + y2 = max (ya, yb) + i + call ep_gindata (ep, x1, x2, y1, y2) + EP_OUTDATA(ep) = NULL + call ep_dosurface (ep) + case 'q': # Quit and save + case 'u': # Undo + if (EP_OUTDATA(ep) != NULL && EP_INDATA(ep) != NULL) { + call malloc (temp, EP_NPTS(ep), TY_REAL) + call amovr (Memr[EP_OUTDATA(ep)], Memr[temp], + EP_NPTS(ep)) + call amovr (Memr[EP_INDATA(ep)], + Memr[EP_OUTDATA(ep)], EP_NPTS(ep)) + call amovr (Memr[temp], Memr[EP_INDATA(ep)], + EP_NPTS(ep)) + call mfree (temp, TY_REAL) + change = YES + } else + call eprintf ("Can't undo last change\007\n") + case 'r', 'E', 'P', 'R', 'Z', '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9': + if (EP_DISPLAY(ep) == YES) { + call ep_zoom (ep, xa, ya, xb, yb, key, erase) + newdisplay = YES + } + case 'Q': # Quit and no save + changes = 0 + case 'I': # Immediate interrupt + call imdelete (EP_WORK(ep)) + call fatal (1, "Interrupt") + default: + call printf ("\007") + } + } then + call erract (EA_WARN) + + if (key == 'q' || key == 'Q') + break + + if (change == YES && EP_AUTOSURFACE(ep) == YES) + call ep_dosurface (ep) + + if (change == YES && EP_AUTODISPLAY(ep) == YES) + newdisplay = YES + if (newdisplay == YES && EP_DISPLAY(ep) == YES) + call ep_display (ep, EP_WORK(ep), erase) + + # Log certain commands. Note that this is done after + # centering. + if (EP_LOGFD(ep) != NULL) { + switch (key) { + case 'a', 'c', 'd', 'f', 'j', 'l', 'v': + call fprintf (EP_LOGFD(ep), "%d %d 1 %c\n") + call pargi (xa) + call pargi (ya) + call pargi (key) + call fprintf (EP_LOGFD(ep), "%d %d 1 %c\n") + call pargi (xb) + call pargi (yb) + call pargi (key) + case 'b', 'e', 'k': + call fprintf (EP_LOGFD(ep), "%d %d 1 %c\n") + call pargi ((xa+xb)/2) + call pargi ((ya+yb)/2) + call pargi (key) + case 'u': + if (EP_OUTDATA(ep) != NULL) { + call fprintf (EP_LOGFD(ep), "%c\n") + call pargi (key) + } + case 'm', 'n': + call fprintf (EP_LOGFD(ep), "%d %d 1 %c\n") + call pargi ((xa+xb)/2) + call pargi ((ya+yb)/2) + call pargi (key) + call fprintf (EP_LOGFD(ep), "%d %d 1 %c\n") + call pargi ((x1+x2)/2) + call pargi ((y1+y2)/2) + call pargi (key) + } + } + } + + call imunmap (EP_IM(ep)) + # Only create the output if the input has been changed. + if (changes > 0) { + if (streq (EP_INPUT(ep), EP_OUTPUT(ep))) { + EP_IM(ep) = immap (EP_OUTPUT(ep), READ_WRITE, 0) + im = immap (EP_WORK(ep), READ_ONLY, 0) + do i = 1, IM_LEN(EP_IM(ep),2) + call amovr (Memr[imgl2r(im,i)], + Memr[impl2r(EP_IM(ep),i)], IM_LEN(im,1)) + call imunmap (im) + call imunmap (EP_IM(ep)) + call imdelete (EP_WORK(ep)) + } else { + if (imaccess (EP_OUTPUT(ep), READ_ONLY) == YES) + call imdelete (EP_OUTPUT(ep)) + call imrename (EP_WORK(ep), EP_OUTPUT(ep)) + } + } else + call imdelete (EP_WORK(ep)) + + # Check for a new image based on a colon command. This case + # always uses the input image name as output. + if (newimage == YES) { + call strcpy (EP_INPUT(ep), EP_OUTPUT(ep), EP_SZFNAME) + goto newim_ + } + } + + # Finish up. + if (EP_LOGFD(ep) != NULL) + call close (EP_LOGFD(ep)) + call imtclose (inlist) + call imtclose (outlist) + call sfree (sp) +end |