aboutsummaryrefslogtreecommitdiff
path: root/pkg/images/tv/imedit
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/images/tv/imedit')
-rw-r--r--pkg/images/tv/imedit/bpmedit.cl69
-rw-r--r--pkg/images/tv/imedit/bpmedit.key51
-rw-r--r--pkg/images/tv/imedit/epbackground.x71
-rw-r--r--pkg/images/tv/imedit/epcol.x80
-rw-r--r--pkg/images/tv/imedit/epcolon.x335
-rw-r--r--pkg/images/tv/imedit/epconstant.x51
-rw-r--r--pkg/images/tv/imedit/epdisplay.x196
-rw-r--r--pkg/images/tv/imedit/epdosurface.x35
-rw-r--r--pkg/images/tv/imedit/epgcur.x127
-rw-r--r--pkg/images/tv/imedit/epgdata.x70
-rw-r--r--pkg/images/tv/imedit/epgsfit.x74
-rw-r--r--pkg/images/tv/imedit/epimcopy.x72
-rw-r--r--pkg/images/tv/imedit/epinput.x55
-rw-r--r--pkg/images/tv/imedit/epix.h50
-rw-r--r--pkg/images/tv/imedit/epline.x80
-rw-r--r--pkg/images/tv/imedit/epmask.x177
-rw-r--r--pkg/images/tv/imedit/epmove.x129
-rw-r--r--pkg/images/tv/imedit/epnoise.x95
-rw-r--r--pkg/images/tv/imedit/epreplace.gx167
-rw-r--r--pkg/images/tv/imedit/epreplace.x260
-rw-r--r--pkg/images/tv/imedit/epsearch.x90
-rw-r--r--pkg/images/tv/imedit/epsetpars.x75
-rw-r--r--pkg/images/tv/imedit/epstatistics.x147
-rw-r--r--pkg/images/tv/imedit/epsurface.x46
-rw-r--r--pkg/images/tv/imedit/imedit.key84
-rw-r--r--pkg/images/tv/imedit/mkpkg38
-rw-r--r--pkg/images/tv/imedit/t_imedit.x305
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