diff options
author | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
---|---|---|
committer | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
commit | 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch) | |
tree | 4464880c571602d54f6ae114729bf62a89518057 /pkg/images/tv/iis/src | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/images/tv/iis/src')
29 files changed, 4652 insertions, 0 deletions
diff --git a/pkg/images/tv/iis/src/blink.x b/pkg/images/tv/iis/src/blink.x new file mode 100644 index 00000000..fc176f7a --- /dev/null +++ b/pkg/images/tv/iis/src/blink.x @@ -0,0 +1,132 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include <gki.h> +include "../lib/ids.h" + +# BLINK -- blink the display. + +procedure blink() + +char token[SZ_LINE] +int tok, count, rate +int sets, button, i +int ctoi(), ip +pointer sp, setp, ptr +int cv_rdbut() +int val, nchar + +define errmsg 10 + +include "cv.com" + +begin + # get rate for blink + + call gargtok (tok, token, SZ_LINE) + if (tok != TOK_NUMBER) { + call eprintf ("Bad blink rate: %s\n") + call pargstr (token) + return + } + ip = 1 + count = ctoi(token, ip, rate) + if (rate < 0) { + call eprintf ("negative rate not legal\n") + return + } + + call smark (sp) + # The "3" is to hold frame/color/quad for one frame; + # the "2" is to allow duplication of each frame so that + # some frames can stay "on" longer. The extra "1" is for graphics. + call salloc (setp, 2 * 3 * (cv_maxframes+1), TY_POINTER) + sets = 0 + + # which frames to blink + + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + while ( (sets <= cv_maxframes+1) && (tok != TOK_NEWLINE) ) { + sets = sets + 1 + ptr = setp + (3 * (sets-1)) + call salloc (Memi[ptr], IDS_MAXIMPL+1, TY_SHORT) + if (tok == TOK_IDENTIFIER) { + if (token[1] == 'f') { + call cv_frame (token[2], Mems[Memi[ptr]]) + if (Mems[Memi[ptr]] == ERR) { + call sfree (sp) + return + } + } + } else if (tok == TOK_NUMBER) { + ip = 1 + nchar = ctoi (token[1], ip, val) + if ( (val < 0) || (val > cv_maxframes)) { + call eprintf ("illegal frame value: %s\n") + call pargstr (token) + call sfree (sp) + return + } + Mems[Memi[ptr]] = val + Mems[Memi[ptr]+1] = IDS_EOD + } else { +errmsg + call eprintf ("Unexpected input: %s\n") + call pargstr (token) + call sfree (sp) + return + } + ptr = ptr + 1 + call salloc (Memi[ptr], IDS_MAXGCOLOR+1, TY_SHORT) + call salloc (Memi[ptr+1], 5, TY_SHORT) + Mems[Memi[ptr]] = IDS_EOD # default all colors + Mems[Memi[ptr+1]] = IDS_EOD # default all quads + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if ( (tok != TOK_IDENTIFIER) && (tok != TOK_NEWLINE)) + goto errmsg + if ((tok == TOK_IDENTIFIER) && (token[1] == 'c')) { + call cv_color (token[2], Mems[Memi[ptr]]) + if (Mems[Memi[ptr]] == ERR) { + call sfree (sp) + return + } + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + } + if ( (tok != TOK_IDENTIFIER) && (tok != TOK_NEWLINE)) + goto errmsg + if ((tok == TOK_IDENTIFIER) && (token[1] == 'q')) { + call cv_quad (token[2], Mems[Memi[ptr+1]]) + if (Mems[Memi[ptr+1]] == ERR) { + call sfree (sp) + return + } + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + } + } # end while + + button = cv_rdbut() # clear any buttons pressed + call eprintf ("Press any button to terminate blink\n") + repeat { + do i = 1, sets { + ptr = setp + 3 * (i-1) + call cvdisplay (IDS_ON, IDS_DISPLAY_I, Mems[Memi[ptr]], + Mems[Memi[ptr+1]], Mems[Memi[ptr+2]]) + # Delay for "rate*100" milliseconds + call zwmsec (rate * 100) + + # Leave something on screen when button pushed + button = cv_rdbut() + if (button > 0) + break + call cvdisplay (IDS_OFF, IDS_DISPLAY_I, Mems[Memi[ptr]], + Mems[Memi[ptr+1]], Mems[Memi[ptr+2]]) + } + } until (button > 0) + + call sfree (sp) +end diff --git a/pkg/images/tv/iis/src/clear.x b/pkg/images/tv/iis/src/clear.x new file mode 100644 index 00000000..60cf69eb --- /dev/null +++ b/pkg/images/tv/iis/src/clear.x @@ -0,0 +1,48 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include "../lib/ids.h" + +# CLEAR -- clear certain frames in the display + +procedure clear() + +char token[SZ_LINE] +int tok +short frames[IDS_MAXIMPL+1] + +define nexttok 10 + +include "cv.com" + +begin + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + + while ( (tok == TOK_IDENTIFIER) || (tok == TOK_NUMBER) ) { + if (tok == TOK_IDENTIFIER) { + switch (token[1]) { + case 'a', 'g': + # all colors + call cvclearg (short(IDS_EOD), short (IDS_EOD)) + if (token[1] == 'g') + goto nexttok + frames[1] = IDS_EOD + + case 'f': + call cv_frame (token[2], frames) + } + } else + call cv_frame (token[1], frames) + + call cvcleari (frames) + if (token[1] == 'a') + return + + # get next token +nexttok + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + } +end diff --git a/pkg/images/tv/iis/src/cv.com b/pkg/images/tv/iis/src/cv.com new file mode 100644 index 00000000..ec9c70e7 --- /dev/null +++ b/pkg/images/tv/iis/src/cv.com @@ -0,0 +1,16 @@ +# common block for cv + +pointer cv_gp # file descriptor to write +pointer cv_stack # working space for escape sequences +int cv_maxframes # device max frames +int cv_maxgraph # device max graph planes +int cv_xcen, cv_ycen # user pixel coords of center of dev. +int cv_xres, cv_yres # device resolution +int cv_zres # device z resolution +real cv_xcon, cv_ycon # conversion from NDC to GKI +int cv_grch # graphics channel +real cv_xwinc, cv_ywinc # cursor position for window command + +common /cvcom/ cv_gp, cv_stack, cv_maxframes, cv_maxgraph, cv_xcen, cv_ycen, + cv_xres, cv_yres, cv_zres, cv_xcon, cv_ycon, cv_grch, + cv_xwinc, cv_ywinc diff --git a/pkg/images/tv/iis/src/cv.h b/pkg/images/tv/iis/src/cv.h new file mode 100644 index 00000000..80f3016b --- /dev/null +++ b/pkg/images/tv/iis/src/cv.h @@ -0,0 +1,51 @@ +# constants for cv package...should come from a graphcap entry + +# These are one based. +define CV_XCEN 257 +define CV_YCEN 256 + +define CV_XRES 512 +define CV_YRES 512 +define CV_ZRES 256 + +define CV_MAXF 4 +define CV_MAXG 7 + +define CV_GRCHNUM 16 + +# CVLEN is just the *estimated* never to be exceeded amount of storage needed +# to set up the escape sequence. It could be determined dynamically by +# changing cv_move to count elements instead of moving them. Then the known +# counts would be used with amovs to hustle the elements into the "salloc'ed" +# space. Instead, with a static count, we can salloc once upon entering +# the cv program and free up at exit. + +define CVLEN 128 + +# Following are from "display.h"... only SAMPLE_SIZE and MAXLOG needed +# as of May, 1985. But we might incorporate other programs from "tv", +# so leave them. + +# Size limiting parameters. + +define MAXCHAN 2 +define SAMPLE_SIZE 600 + +# If a logarithmic greyscale transformation is desired, the input range Z1:Z2 +# will be mapped into the range 1.0 to 10.0 ** MAXLOG before taking the log +# to the base 10. + +define MAXLOG 3 + +# The following parameter is used to compare display pixel coordinates for +# equality. It determines the maximum permissible magnification. The machine +# epsilon is not used because the computations are nontrivial and accumulation +# of error is a problem. + +define DS_TOL (1E-4) + +# These parameters are needed for user defined transfer functions. + +define SZ_BUF 4096 +define STARTPT 0.0E0 +define ENDPT 4095.0E0 diff --git a/pkg/images/tv/iis/src/cv.x b/pkg/images/tv/iis/src/cv.x new file mode 100644 index 00000000..a169a402 --- /dev/null +++ b/pkg/images/tv/iis/src/cv.x @@ -0,0 +1,175 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <fio.h> +include <fset.h> +include "../lib/ids.h" +include <gki.h> +include <ctotok.h> +include <error.h> +include "cv.h" + +# Captain Video + +procedure t_cv() + +pointer gp +char device[SZ_FNAME] +char command[SZ_LINE] + +pointer gopen(), sp +int dd[LEN_GKIDD] + +int scan, tok, envgets() + +include "cv.com" + +begin + call smark (sp) + call salloc (cv_stack, CVLEN, TY_SHORT) + + if (envgets ("stdimage", device, SZ_FNAME) == 0) + call error (EA_FATAL, + "variable 'stdimage' not defined in environment") + + call ids_open (device, dd) + call gki_inline_kernel (STDIMAGE, dd) + gp = gopen ( device, READ_WRITE, STDIMAGE) + + call fseti (STDIMAGE, F_TYPE, SPOOL_FILE) + call fseti (STDIMAGE, F_CANCEL, OK) + call ids_grstream (STDIMAGE) + + # to do: + # initialize local variables: image display size, etc + # instead of defines such as MCXSCALE, etc + cv_maxframes = CV_MAXF + cv_maxgraph = CV_MAXG + cv_xcen = CV_XCEN + cv_ycen = CV_YCEN + cv_xres = CV_XRES + cv_yres = CV_YRES + cv_zres = CV_ZRES + cv_gp = gp + cv_xcon = real(GKI_MAXNDC+1)/CV_XRES + cv_ycon = real(GKI_MAXNDC+1)/CV_YRES + cv_grch = CV_GRCHNUM + cv_xwinc = -1. # Flag: Don't know what lut is + + repeat { + call printf (":-) ") + call flush (STDOUT) + if (scan() == EOF) + break + call gargtok(tok, command, SZ_LINE) + if ((tok == TOK_EOS) || (tok == TOK_NEWLINE)) + next + # decode next command + call strlwr(command) + switch (command[1]) { + case 'x', 'q': + break + + + case 'b': + call blink + + case 'c': + if (command[2] == 'l') + call clear + else + call rdcur + + case 'd': + call display(command[2]) + + case 'e': # erase means clear + call clear + + case 'h', '?': + call help + + # case 'l': + # call load + + case 'm': + call match + + case 'o': + call offset + + case 'p': + if ( command[2] == 's') + call map(command[2]) # pseudo color + else + call pan + + case 'r': + if (command[2] == 'e') + call reset + else + call range + + case 's': + if (command[2] == 'n') + call snap + else + call split + + case 't': + call tell + + case 'w': + if (command[2] == 'r') + call text + else + call window + + case 'z': + call zoom + + default: + call eprintf("unknown command: %s\n") + call pargstr(command[1]) + + } # end switch statement + + } # end repeat statment + + # all done + + call gclose ( gp ) + call ids_close + call sfree (sp) +end + + +# HELP -- print informative message + +procedure help() + +begin + call eprintf ("--- () : optional; [] : select one; N : number; C/F/Q : see below\n") + call eprintf ("b(link) N F (C Q) (F (C Q)..) blink N = 10 is one second\n") + call eprintf ("c(ursor) [on off F] cursor\n") + call eprintf ("di F (C Q) [on off] display image\n") + call eprintf ("dg C (F Q) [on off] display graphics\n") + call eprintf ("e(rase) [N a(ll) g(raphics) F] erase (clear)\n") + #call eprintf ("l(oad) load a frame\n") + call eprintf ("m(atch) (o) F (C) (to) (F) (C) match (output) lookup table\n") + call eprintf ("o(ffset) C N offset color N: 0 to +- 4095\n") + call eprintf ("p(an) (F) pan images\n") + call eprintf ("ps(eudo) (o) (F C) (rn sn) pseudo color mapping rn/sn: random n/seed n\n") + call eprintf ("r(ange) N (C) (N C ...) scale image N: 1-8\n") + call eprintf ("re(set) [r i t a] reset display registers/image/tables/all\n") + call eprintf ("sn(ap) (C) snap a picture\n") + call eprintf ("s(plit) [c o px,y nx,y] split picture\n") + call eprintf ("t(ell) tell display state\n") + call eprintf ("w(indow) (o) (F C) window (output) frames\n") + call eprintf ("wr(ite) [F C] text write text to frame/graphics\n") + call eprintf ("z(oom) N (F) zoom frames N: 1-8\n") + call eprintf ("x or q exit/quit\n") + call eprintf ("--- C: letter c followed by r/g/b/a or, for snap r,g,b,m,bw,rgb,\n") + call eprintf ("--- or for dg r/g/b/y/p/m/w, as 'cr', 'ca', or 'cgb'\n") + call eprintf ("--- F: f followed by a frame number or 'a' for all\n") + call eprintf ("--- Q: q followed by quadrant number or t,b,l,r for top, bottom,...\n") +end diff --git a/pkg/images/tv/iis/src/cvparse.x b/pkg/images/tv/iis/src/cvparse.x new file mode 100644 index 00000000..46aba66b --- /dev/null +++ b/pkg/images/tv/iis/src/cvparse.x @@ -0,0 +1,196 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "../lib/ids.h" +include <ctype.h> + +# CVPARSE -- parsing routines for the cv package + +# CV_FRAME -- parse a frame specification + +procedure cv_frame(str, result) + +char str[ARB] # input string +short result[ARB] # result string + +int ip +int op +int i +int used[IDS_MAXIMPL] +int gused + +include "cv.com" + +begin + if (str[1] == 'a') { + result[1] = IDS_EOD + return + } + call aclrs(used,IDS_MAXIMPL) + gused = 0 + op = 1 + for (ip = 1; str[ip] != EOS; ip = ip + 1) { + if (!IS_DIGIT(str[ip])) { + if (str[ip] == 'g') + gused = 1 + else { + call eprintf("unknown frame specifier: %c\n") + call pargc(str[ip]) + } + next + } + i = TO_INTEG (str[ip]) # fail if > than 9 planes! use ctoi() + if ((i < 1) || (i > cv_maxframes) ) { + call eprintf ("out of bounds frame: %d\n") + call pargi(i) + next + } else + used[i] = 1 + } + do i= 1,IDS_MAXIMPL + if (used[i] != 0) { + result[op] = i + op = op + 1 + } + if (gused != 0) { + result[op] = cv_grch + op = op + 1 + } + if (op > 1) + result[op] = IDS_EOD + else + result[op] = ERR +end + + +# CV_COLOR -- parse a color specification + +procedure cv_color(str, result) + +char str[ARB] # input string +short result[ARB] # result string + +int ip +int op +int i +short val +short used[IDS_MAXGCOLOR+1] + +include "cv.com" + +begin + if (str[1] == 'a') { + result[1] = IDS_EOD + return + } + call aclrs (used, IDS_MAXGCOLOR+1) + op = 1 + for (ip = 1; str[ip] != EOS; ip = ip + 1) { + switch (str[ip]) { + case 'r': + val = IDS_RED + + case 'g': + val = IDS_GREEN + + case 'b': + val = IDS_BLUE + + case 'y': + val = IDS_YELLOW + + case 'w': + val = IDS_WHITE + + case 'p': + val = IDS_RDBL + + case 'm': + val = IDS_GRBL + + default: + call eprintf("unknown color: %c\n") + call pargc(str[ip]) + next + } + used[val] = 1 + } + do i = 1, IDS_MAXGCOLOR+1 + if (used[i] != 0) { + result[op] = i + op = op + 1 + } + if (op > 1) + result[op] = IDS_EOD + else + result[op] = ERR +end + + +# CV_QUAD -- parse a quad specification + +procedure cv_quad(str, result) + +char str[ARB] # input string +short result[ARB] # result string + +int ip +int op +int i +short used[4] + +include "cv.com" + +begin + if (str[1] == 'a') { + result[1] = IDS_EOD + return + } + call aclrs(used, 4) + op = 1 + for (ip = 1; str[ip] != EOS; ip = ip + 1) { + if (!IS_DIGIT(str[ip])) { + switch(str[ip]) { + case 'a': + call amovks (1, used, 4) + + case 't': + used[1] = 1 + used[2] = 1 + + case 'b': + used[3] = 1 + used[4] = 1 + + case 'l': + used[2] = 1 + used[3] = 1 + + case 'r': + used[1] = 1 + used[4] = 1 + + default: + call eprintf("unknown quad specifier: %c\n") + call pargc(str[ip]) + } + } else { + i = TO_INTEG (str[ip]) + if ((i < 1) || (i > 4)) { + call eprintf ("out of bounds quad: %d\n") + call pargi(i) + next + } else + used[i] = 1 + } + } + do i = 1,4 { + if (used[i] != 0) { + result[op] = i + op = op + 1 + } + } + if (op > 1) + result[op] = IDS_EOD + else + result[op] = ERR +end diff --git a/pkg/images/tv/iis/src/cvulut.x b/pkg/images/tv/iis/src/cvulut.x new file mode 100644 index 00000000..683c9500 --- /dev/null +++ b/pkg/images/tv/iis/src/cvulut.x @@ -0,0 +1,130 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> +include <ctype.h> +include "cv.h" + +# CV_ULUT -- Generates a look up table from data supplied by user. The +# data is read from a two column text file of intensity, greyscale values. +# The input data are sorted, then mapped to the x range [0-4096]. A +# piecewise linear look up table of 4096 values is then constructed from +# the (x,y) pairs given. A pointer to the look up table, as well as the z1 +# and z2 intensity endpoints, is returned. + +procedure cv_ulut (fname, z1, z2, lut) + +char fname[SZ_FNAME] # Name of file with intensity, greyscale values +real z1 # Intensity mapped to minimum gs value +real z2 # Intensity mapped to maximum gs value +pointer lut # Look up table - pointer is returned + +pointer sp, x, y +int nvalues, i, j, x1, x2, y1 +real delta_gs, delta_xv, slope +errchk cv_rlut, cv_sort, malloc + +begin + call smark (sp) + call salloc (x, SZ_BUF, TY_REAL) + call salloc (y, SZ_BUF, TY_REAL) + + # Read intensities and greyscales from the user's input file. The + # intensity range is then mapped into a standard range and the + # values sorted. + + call cv_rlut (fname, Memr[x], Memr[y], nvalues) + call alimr (Memr[x], nvalues, z1, z2) + call amapr (Memr[x], Memr[x], nvalues, z1, z2, STARTPT, ENDPT) + call cv_sort (Memr[x], Memr[y], nvalues) + + # Fill lut in straight line segments - piecewise linear + call malloc (lut, SZ_BUF, TY_SHORT) + do i = 1, nvalues-1 { + delta_gs = Memr[y+i] - Memr[y+i-1] + delta_xv = Memr[x+i] - Memr[x+i-1] + slope = delta_gs / delta_xv + x1 = int (Memr[x+i-1]) + x2 = int (Memr[x+i]) + y1 = int (Memr[y+i-1]) + do j = x1, x2-1 + Mems[lut+j-1] = y1 + slope * (j-x1) + } + + call sfree (sp) +end + + +# CV_RLUT -- Read text file of x, y, values. + +procedure cv_rlut (utab, x, y, nvalues) + +char utab[SZ_FNAME] # Name of list file +real x[SZ_BUF] # Array of x values, filled on return +real y[SZ_BUF] # Array of y values, filled on return +int nvalues # Number of values in x, y vectors - returned + +int n, fd +pointer sp, lbuf, ip +real xval, yval +int getline(), open() +errchk open, sscan, getline, malloc + +begin + call smark (sp) + call salloc (lbuf, SZ_LINE, TY_CHAR) + + iferr (fd = open (utab, READ_ONLY, TEXT_FILE)) + call error (0, "Error opening user table") + + n = 0 + + while (getline (fd, Memc[lbuf]) != EOF) { + # Skip comment lines and blank lines. + if (Memc[lbuf] == '#') + next + for (ip=lbuf; IS_WHITE(Memc[ip]); ip=ip+1) + ; + if (Memc[ip] == '\n' || Memc[ip] == EOS) + next + + # Decode the points to be plotted. + call sscan (Memc[ip]) + call gargr (xval) + call gargr (yval) + + n = n + 1 + if (n > SZ_BUF) + call error (0, + "Intensity transformation table cannot exceed 4096 values") + + x[n] = xval + y[n] = yval + } + + nvalues = n + call close (fd) + call sfree (sp) +end + + +# CV_SORT -- Bubble sort of paired arrays. + +procedure cv_sort (xvals, yvals, nvals) + +real xvals[nvals] # Array of x values +real yvals[nvals] # Array of y values +int nvals # Number of values in each array + +int i, j +real temp +define swap {temp=$1;$1=$2;$2=temp} + +begin + for (i = nvals; i > 1; i = i - 1) + for (j = 1; j < i; j = j + 1) + if (xvals[j] > xvals[j+1]) { + # Out of order; exchange y values + swap (xvals[j], xvals[j+1]) + swap (yvals[j], yvals[j+1]) + } +end diff --git a/pkg/images/tv/iis/src/cvutil.x b/pkg/images/tv/iis/src/cvutil.x new file mode 100644 index 00000000..81721081 --- /dev/null +++ b/pkg/images/tv/iis/src/cvutil.x @@ -0,0 +1,538 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <gset.h> +include <gki.h> +include <imhdr.h> +include "cv.h" +include "../lib/ids.h" + +# CVUTIL -- utility control routines for cv package + +############ CLEAR display ############ +# CVCLEARG -- clear all of graphics (bit) planes + +procedure cvclearg (frame, color) + +short frame[ARB] +short color[ARB] + +int count +int cv_move() + +include "cv.com" + +begin + count = cv_move (frame, Mems[cv_stack]) + count = count + cv_move (color, Mems[cv_stack+count]) + call gescape (cv_gp, IDS_SET_GP, Mems[cv_stack], count) + call gclear (cv_gp) +end + +# CVCLEARI -- clear specified image frames + +procedure cvcleari (frames) + +short frames[ARB] + +include "cv.com" + +begin + call cv_iset (frames) + call gclear (cv_gp) +end + +############ CURSOR and BUTTON ############ +# CV_RDBUT -- read button on trackball (or whatever) +# if none pressed, will get zero back + +int procedure cv_rdbut() + +int oldcnum +real x, y +int button +int gstati + +include "cv.com" + +begin + oldcnum = gstati (cv_gp, G_CURSOR) + call gseti (cv_gp, G_CURSOR, IDS_BUT_RD) + call ggcur (cv_gp, x, y, button) + call gseti (cv_gp, G_CURSOR, oldcnum) + return(button) +end + +# CV_WTBUT -- wait for button to be pressed, then read it + +int procedure cv_wtbut() + +int oldcnum +real x, y +int button +int gstati + +include "cv.com" + +begin + oldcnum = gstati (cv_gp, G_CURSOR) + call gseti (cv_gp, G_CURSOR, IDS_BUT_WT) + call ggcur (cv_gp, x, y, button) + call gseti (cv_gp, G_CURSOR, oldcnum) + return(button) +end + +# CV_RCUR -- read cursor. The cursor read/set routines do not restore +# the cursor number...this to avoid numerous stati/seti calls that +# usually are not needed. + +procedure cv_rcur (cnum, x, y) + +int cnum +real x,y +int junk + +include "cv.com" + +begin + call gseti (cv_gp, G_CURSOR, cnum) + call ggcur (cv_gp, x, y, junk) +end + +# CV_SCUR -- set cursor + +procedure cv_scur (cnum, x, y) + +int cnum +real x,y + +include "cv.com" + +begin + call gseti (cv_gp, G_CURSOR, cnum) + call gscur (cv_gp, x, y) +end + + +# CV_RCRAW -- read the raw cursor (return actual screen coordinates). + +procedure cv_rcraw (x, y) + +real x,y + +include "cv.com" + +begin + call cv_rcur (IDS_CRAW, x, y) +end + +# CV_SCRAW -- set raw cursor + +procedure cv_scraw (x, y) + +real x,y + +include "cv.com" + +begin + call cv_scur (IDS_CRAW, x, y) +end + + +# cvcur -- turn cursor on or off + +procedure cvcur (instruction) + +int instruction + +include "cv.com" + +begin + Mems[cv_stack] = IDS_CURSOR + Mems[cv_stack+1] = IDS_WRITE + Mems[cv_stack+2] = 1 + Mems[cv_stack+3] = IDS_EOD + Mems[cv_stack+4] = IDS_EOD + Mems[cv_stack+5] = 1 + Mems[cv_stack+6] = instruction + call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], 7) +end + +############ DISPLAY ############ +# cvdisplay + +procedure cvdisplay (instruction, device, frame, color, quad) + +int instruction +int device +short frame, color, quad + +int i +int cv_move() + +include "cv.com" + +begin + Mems[cv_stack] = instruction + i = cv_move (frame, Mems[cv_stack+1]) + i = i + cv_move (color, Mems[cv_stack+1+i]) + i = i + cv_move (quad, Mems[cv_stack+1+i]) + call gescape (cv_gp, device, Mems[cv_stack], 1+i) +end + +############ MATCH ############ +# cvmatch -- build match escape sequence + +procedure cvmatch (lt, fr, cr, frames, color) + +int lt # type +short fr[ARB] # reference frame and color +short cr[ARB] +short frames[ARB] # frames to be changed +short color[ARB] # and colors + +int count, n +int cv_move() + +include "cv.com" + +begin + Mems[cv_stack] = IDS_MATCH + Mems[cv_stack+1] = lt + count = cv_move (fr, Mems[cv_stack+3]) + count = count + cv_move (cr, Mems[cv_stack+3+count]) + n = count + Mems[cv_stack+count+3] = 0 # unused offset + count = count + cv_move (frames, Mems[cv_stack+4+count]) + count = count + cv_move (color, Mems[cv_stack+4+count]) + Mems[cv_stack+2] = count - n + call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], count+4) +end + +############ OFFSET ############ +# cvoffset -- set offset registers + +procedure cvoffset( color, data) + +short color[ARB] +short data[ARB] + +int count, cv_move() +int i + +include "cv.com" + +begin + Mems[cv_stack] = IDS_OUT_OFFSET + Mems[cv_stack+1] = IDS_WRITE + Mems[cv_stack+3] = IDS_EOD # no-op the frames slot + count = cv_move (color, Mems[cv_stack+4]) + Mems[cv_stack+4+count] = 1 # (unused) offset + i = cv_move (data, Mems[cv_stack+5+count]) + i = i - 1 # don't include EOD of "data" + Mems[cv_stack+2] = i + call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], i+count+5) +end + +############ PAN ############ +# cvpan -- move the image(s) around +# The x,y coordinates are NDC that, it is assumed, came from a cursor +# read, and therefore are of the form +# ((one_based_pixel-1)/(resolution)) *(GKI_MAXNDC+1) / GKI_MAXNDC +# The division by GKI_MAXNDC turns into NDC what was GKI ranging from +# 0 through 511*64 (for IIS) which conforms to the notion of specifying +# each pixel by its left/bottom GKI boundary. + +procedure cvpan (frames, x, y) + +short frames[ARB] +real x,y # position in NDC + +int count, cv_move() + +include "cv.com" + +begin + Mems[cv_stack] = IDS_SCROLL + Mems[cv_stack+1] = IDS_WRITE + Mems[cv_stack+2] = 3 + count = cv_move (frames, Mems[cv_stack+3]) + Mems[cv_stack+3+count] = IDS_EOD # all colors + Mems[cv_stack+4+count] = 1 # (unused) offset + Mems[cv_stack+5+count] = x * GKI_MAXNDC + Mems[cv_stack+6+count] = y * GKI_MAXNDC + Mems[cv_stack+7+count] = IDS_EOD # for all frames + call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], count+8) +end + +############ RANGE ############ +# cvrange -- scale ouput before final look up table + +procedure cvrange ( color, range) + +short color[ARB] +short range[ARB] + +int cv_move(), count, i + +include "cv.com" + +begin + Mems[cv_stack] = IDS_RANGE + Mems[cv_stack+1] = IDS_WRITE + Mems[cv_stack+3] = IDS_EOD # all frames + count = cv_move (color, Mems[cv_stack+4]) + Mems[cv_stack+4+count] = 1 # (unused) offset + i = cv_move (range, Mems[cv_stack+5+count]) + i = i - 1 # don't include EOD of "range" + Mems[cv_stack+2] = i + call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], i+count+5) +end + +############ RESET display ############ +# cvreset -- reset display +# SOFT -- everything but lookup tables and image/graphics planes +# MEDIUM -- everything but image/graphics planes +# HARD -- everything...planes are cleared, all images OFF + +procedure cvreset (hardness) + +int hardness + +include "cv.com" + +begin + Mems[cv_stack] = hardness + call gescape (cv_gp, IDS_RESET, Mems[cv_stack], 1) +end + + +############ SNAP a picture ############ +# cvsnap -- takes a full picture of image display + +procedure cvsnap (fname, snap_color) + +char fname[ARB] # image file name +int snap_color + +pointer im, immap(), impl2s() +int i, factor +real y + +include "cv.com" + +begin + im = immap(fname, NEW_FILE, 0) + IM_PIXTYPE(im) = TY_SHORT + IM_LEN(im,1) = cv_xres + IM_LEN(im,2) = cv_yres + + Mems[cv_stack] = IDS_SNAP + Mems[cv_stack+1] = IDS_WRITE + Mems[cv_stack+2] = 1 # frame, color are not relevant + Mems[cv_stack+3] = IDS_EOD + Mems[cv_stack+4] = IDS_EOD + Mems[cv_stack+5] = 0 + Mems[cv_stack+6] = snap_color + call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], 7) + + factor = cv_yres/10 + 1 + call eprintf (" (%% done: ") + call flush (STDERR) + do i = 0, cv_yres-1 { + if ( mod(i,factor) == 0) { + call eprintf ("%d ") + call pargi (int(10*i/cv_yres)*10) + call flush (STDERR) + } + y = real(i)*cv_ycon / GKI_MAXNDC. + call ggcell (cv_gp, Mems[impl2s(im,i+1)], cv_xres, 1, 0.0, + y, 1.0, y) + } + call eprintf ("100)\n") + + call imunmap(im) + Mems[cv_stack] = IDS_R_SNAPDONE + call gescape (cv_gp, IDS_RESET, Mems[cv_stack], 1) +end + +############ SPLIT ############ +# cvsplit -- set split screen position + +procedure cvsplit (x, y) + +real x,y # NDC coordinates + +include "cv.com" + +begin + Mems[cv_stack] = IDS_SPLIT + Mems[cv_stack+1] = IDS_WRITE + Mems[cv_stack+2] = 2 + Mems[cv_stack+3] = IDS_EOD # no-op frame and color + Mems[cv_stack+4] = IDS_EOD + Mems[cv_stack+5] = 1 # (unused) offset + # NOTE multiplacation by MAXNDC+1 ... x, and y, are never == 1.0 + # ( see split.x) + # and truncation effects will work out just right, given what the + # image display kernel does with these numbers + Mems[cv_stack+6] = x * (GKI_MAXNDC+1) + Mems[cv_stack+7] = y * (GKI_MAXNDC+1) + call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], 8) +end + +############ TEXT ############ +# Write text + +procedure cvtext (x, y, text, size) + +real x, y, size +char text[ARB] + +char format[SZ_LINE] + +include "cv.com" + +begin + call sprintf (format, SZ_LINE, "s=%f") + call pargr (size) + call gtext (cv_gp, x, y, text, format) +end + +############ WHICH ############ +# Tell which frames are one. The best we can do now is +# tell if any, and if so, which is the "first" + +procedure cvwhich (fr) + +short fr[ARB] + +real x,y +int cnum, oldcnum +int gstati + +include "cv.com" + +begin + # Use here the fact that if cursor number is zero, the + # kernel will return the number of the first displayed + # frame, or "ERR" if none. + oldcnum = gstati (cv_gp, G_CURSOR) + cnum = 0 + call gseti (cv_gp, G_CURSOR, cnum) + call ggcur (cv_gp, x, y, cnum) + call gseti (cv_gp, G_CURSOR, oldcnum) + fr[1] = cnum + fr[2] = IDS_EOD +end + +############ WLUT ############ +# cvwlut ... change lookup tables +# the data is in form of line endpoints. + +procedure cvwlut (device, frames, color, data, n) + +int device +short frames[ARB] +short color[ARB] +short data[ARB] +int n + +int count, cv_move() + +include "cv.com" + +begin + # Device had better refer to a look-up table, or who knows + # what will happen! + Mems[cv_stack] = device + Mems[cv_stack+1] = IDS_WRITE + Mems[cv_stack+2] = n + count = cv_move (frames, Mems[cv_stack+3]) + count = count + cv_move (color, Mems[cv_stack+3+count]) + Mems[cv_stack+3+count] = 1 # (unused) offset + call amovs (data, Mems[cv_stack+count+4],n) + call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], n+count+4) +end + +############ ZOOM ############ +# cvzoom -- zoom the image +# See comment under PAN about x and y. + +procedure cvzoom (frames, power, x, y) + +short frames[ARB] +int power +real x,y + +int count, cv_move() + +include "cv.com" + +begin + Mems[cv_stack] = IDS_ZOOM + Mems[cv_stack+1] = IDS_WRITE + Mems[cv_stack+2] = 3 + count = cv_move (frames, Mems[cv_stack+3]) + Mems[cv_stack+3+count] = IDS_EOD # (unused) color + Mems[cv_stack+4+count] = IDS_EOD # (unused) offset + Mems[cv_stack+5+count] = power + Mems[cv_stack+6+count] = x * GKI_MAXNDC + Mems[cv_stack+7+count] = y * GKI_MAXNDC + call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], count+8) +end + +############ SUBROUTINES ############## +# CV_MOVE -- transfer an array into the escape data array; returns number +# of items transfered. + +int procedure cv_move (in, out) + +short in[ARB] +short out[ARB] + +int count + +begin + count = 0 + repeat { + count = count + 1 + out[count] = in[count] + } until (in[count] == IDS_EOD) + return (count) +end + +# CV_ISET -- Tell the image kernel that i/o is to be done for the +# specified frame/frames. + +procedure cv_iset (frames) + +short frames[ARB] + +short idata[30] +int i, cv_move() + +include "cv.com" + +begin + i = cv_move (frames, idata) + idata[i+1] = IDS_EOD # all bit planes + call gescape (cv_gp, IDS_SET_IP, idata, i+1) +end + +# CV_GSET -- Tell the image kernel that i/o is to be done for the +# specified colors. + +procedure cv_gset (colors) + +short colors[ARB] + +short idata[30] +int i, cv_move() + +include "cv.com" + +begin + idata[1] = IDS_EOD # all "frames" + i = cv_move (colors, idata[2]) + call gescape (cv_gp, IDS_SET_GP, idata, i+1) +end diff --git a/pkg/images/tv/iis/src/display.x b/pkg/images/tv/iis/src/display.x new file mode 100644 index 00000000..d04b1365 --- /dev/null +++ b/pkg/images/tv/iis/src/display.x @@ -0,0 +1,104 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include "../lib/ids.h" + +# DISPLAY -- Turn frames on or off + +procedure display(command) + +char command[ARB] + +int tok +char token[SZ_LINE] +short color[IDS_MAXGCOLOR+1] +short frames[IDS_MAXIMPL+1] +short quad[5] +short instruction +int escape +include "cv.com" + +begin + if (command[1] == 'i') + escape = IDS_DISPLAY_I + else if (command[1] == 'g') + escape = IDS_DISPLAY_G + else { + call eprintf ("Only 'di' or 'dg' are understood\n") + return + } + + instruction = ERR + frames[1] = ERR + color[1] = ERR + quad[1] = IDS_EOD + + repeat { + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if ( tok == TOK_IDENTIFIER) { + switch (token[1]) { + case 'c': + call cv_color (token[2], color) + if (color[1] == ERR) + return + + case 'f': + call cv_frame (token[2], frames) + if (frames[1] == ERR) + return + + + case 'o': + if (token[2] == 'n') + instruction = IDS_ON + else if (token[2] == 'f') + instruction = IDS_OFF + + case 'q': + call cv_quad (token[2], quad) + if (quad[1] == ERR) + return + } + } else if (tok == TOK_NUMBER) { + call cv_frame (token[1], frames) + if (frames[1] == ERR) + return + } + } until ( tok == TOK_NEWLINE ) + + + # Require a frame number, but allow default of color and quad to "all". + # But, for graphics, default the frame and require a color. + # In either case, for OFF, allow all defaults. + if (escape == IDS_DISPLAY_I) { + if ((instruction == IDS_OFF) && (frames[1] == ERR)) + frames[1] = IDS_EOD + if ( color[1] == ERR) + color[1] = IDS_EOD + } else { + if ((instruction == IDS_OFF) && ( color[1] == ERR) ) + color[1] = IDS_EOD + if ( frames[1] == ERR) + frames[1] = IDS_EOD + } + + if (frames[1] == ERR) { + call eprintf ("Frame specification required\n") + return + } + if (color[1] == ERR) { + call eprintf ("Color specification required\n") + return + } + + # if neither "on" nor "off", then turn off all, and turn + # on the specified frames + if (instruction == ERR) { + call cvdisplay (IDS_OFF , escape, short(IDS_EOD), + short(IDS_EOD), short(IDS_EOD)) + instruction = IDS_ON + } + call cvdisplay (instruction, escape, frames, color, quad) +end diff --git a/pkg/images/tv/iis/src/gwindow.h b/pkg/images/tv/iis/src/gwindow.h new file mode 100644 index 00000000..5050b304 --- /dev/null +++ b/pkg/images/tv/iis/src/gwindow.h @@ -0,0 +1,34 @@ +# Window descriptor structure. + +define LEN_WDES (5+(W_MAXWC+1)*LEN_WC+80) +define LEN_WC 10 # 4=[XbXeYbYe]+2=tr_type[xy] +define W_MAXWC 5 # max world coord systems +define W_SZIMSECT 79 # image section string + +define W_DEVICE Memi[$1] +define W_FRAME Memi[$1+1] # device frame number +define W_XRES Memi[$1+2] # device resolution, x +define W_YRES Memi[$1+3] # device resolution, y +define W_WC ($1+$2*LEN_WC+5) # ptr to coord descriptor +define W_IMSECT Memc[($1+65-1)*SZ_STRUCT+1] + +# Fields of the WC coordinate descriptor, a substructure of the window +# descriptor. "W_XB(W_WC(w,0))" is the XB field of wc 0 of window W. + +define W_XS Memr[P2R($1)] # starting X value +define W_XE Memr[P2R($1+1)] # ending X value +define W_XT Memi[$1+2] # X transformation type +define W_YS Memr[P2R($1+3)] # starting Y value +define W_YE Memr[P2R($1+4)] # ending Y value +define W_YT Memi[$1+5] # Y transformation type +define W_ZS Memr[P2R($1+6)] # starting Z value (greyscale) +define W_ZE Memr[P2R($1+7)] # ending Z value +define W_ZT Memi[$1+8] # Z transformation type +define W_UPTR Memi[$1+9] # LUT when ZT=USER + +# Types of coordinate and greyscale transformations. + +define W_UNITARY 0 # values map without change +define W_LINEAR 1 # linear mapping +define W_LOG 2 # logarithmic mapping +define W_USER 3 # user specifies transformation diff --git a/pkg/images/tv/iis/src/load1.x b/pkg/images/tv/iis/src/load1.x new file mode 100644 index 00000000..c33cc1dd --- /dev/null +++ b/pkg/images/tv/iis/src/load1.x @@ -0,0 +1,324 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +#### load1.x (from load.x) #### + +include <mach.h> +include <imset.h> +include <imhdr.h> +include <error.h> +include <gki.h> +include <fio.h> +include <fset.h> +include "gwindow.h" +include "../lib/ids.h" +include "cv.h" + +# LOAD - Load an image. The specified image section is mapped into +# the specified section of an image display frame. The mapping involves +# a linear transformation in X and Y and a linear or logarithmic transformation +# in Z (greyscale). Images of all pixel datatypes are supported, and there +# no upper limit on the size of an image. The display device is interfaced +# via GIO metacode. + +procedure t_load() + +char image[SZ_FNAME] +short frame[IDS_MAXIMPL+1] +bool frame_erase, border_erase +pointer im, wdes, sp + +pointer gp +char device[SZ_FNAME] +int dd[LEN_GKIDD] + +int envgets() +short clgets() +bool clgetb() +pointer immap(), gopen() + +include "cv.com" +errchk immap, imunmap, ds_getparams + +begin + call smark (sp) + call salloc (cv_stack, CVLEN, TY_SHORT) + call salloc (wdes, LEN_WDES, TY_STRUCT) + + if (envgets ("stdimage", device, SZ_FNAME) == 0) + call error (EA_FATAL, + "variable 'stdimage' not defined in environment") + + call ids_open (device, dd) + call gki_inline_kernel (STDIMAGE, dd) + # Need READ_WRITE so can call cvdisplay + gp = gopen ( device, READ_WRITE, STDIMAGE) + + call fseti (STDIMAGE, F_TYPE, SPOOL_FILE) + call fseti (STDIMAGE, F_CANCEL, OK) + call ids_grstream (STDIMAGE) + + # to do: + # initialize local variables: image display size, etc + # instead of defines such as MCXSCALE, etc + + cv_maxframes = CV_MAXF + cv_maxgraph = CV_MAXG + cv_xcen = CV_XCEN + cv_ycen = CV_YCEN + cv_xres = CV_XRES + cv_yres = CV_YRES + cv_zres = CV_ZRES + cv_gp = gp + cv_xcon = real(GKI_MAXNDC+1)/CV_XRES + cv_ycon = real(GKI_MAXNDC+1)/CV_YRES + cv_grch = CV_GRCHNUM + cv_xwinc = -1. # Flag: Don't know what lut is + + # Open input imagefile. + call clgstr ("image", image, SZ_FNAME) + im = immap (image, READ_ONLY, 0) + + # Ultimately, we should get a sequence of frames, all of which get + # loaded with the same image. + + frame[1] = clgets ("frame") + frame[2] = IDS_EOD + frame_erase = clgetb ("erase") + + # Optimize for sequential i/o. + call imseti (im, IM_ADVICE, SEQUENTIAL) + + # The frame being displayed does not necessarily change when a new + # frame is loaded. (We might consider letting user select via the + # cv package) + + if (clgetb ("select_frame")) { + call cvdisplay (IDS_OFF, IDS_DISPLAY_I, short(IDS_EOD), + short(IDS_EOD), short(IDS_EOD)) + call cvdisplay (IDS_ON, IDS_DISPLAY_I, frame, short(IDS_EOD), + short(IDS_EOD)) + } + + if (frame_erase) + call cvcleari (frame) + + # Tell GIO what frame(s) to write + call cv_iset (frame) + + # Done with all possible read/write calls to cv package. Fix up so + # don't read device if we erase the frame, so need WRITE_ONLY mode. + # fseti on STDIMAGE didn't work. + + if (frame_erase) { + call gclose (gp) + call gki_inline_kernel (STDIMAGE, dd) + gp = gopen ( device, WRITE_ONLY, STDIMAGE) + cv_gp = gp + call fseti (STDIMAGE, F_TYPE, SPOOL_FILE) + call fseti (STDIMAGE, F_CANCEL, OK) + } + + # Get display parameters and set up transformation. + call ds_getparams (im, wdes, image, frame) + + # Erase the border (space between displayed image section and edge of + # window) only if screen was not erased and border erasing is enabled. + + if (frame_erase) + border_erase = false + else + border_erase = clgetb ("border_erase") + + # Display the image. + call ds_load_display (im, wdes, border_erase) + + call imunmap (im) + + # All done. + call gclose (gp) + call ids_close() + call sfree (sp) +end + + +# DS_GETPARAMS -- Get the parameters controlling how the image is mapped +# into the display frame. Set up the transformations and save in the graphics +# descriptor file. + +procedure ds_getparams (im, wdes, image, frame) + +pointer im, wdes # Image and graphics descriptors +char image[SZ_FNAME] # Should be determined from im +short frame[ARB] + +bool fill, zscale_flag, zrange_flag, zmap_flag +real xcenter, ycenter +real xsize, ysize, pxsize, pysize +real xmag, ymag, xscale, yscale +real z1, z2, contrast +int nsample_lines, ncols, nlines, len_stdline +pointer sp, w, ztrans, lut, lutfile + +bool clgetb() +int clgeti() +real clgetr() +bool streq() + +include "cv.com" + +begin + call smark (sp) + call salloc (ztrans, SZ_FNAME, TY_CHAR) + + # Set up a new graphics descriptor structure defining the coordinate + # transformation used to map the image into the display frame. + + call strcpy (image, W_IMSECT(wdes), W_SZIMSECT) + ncols = IM_LEN(im,1) + nlines = IM_LEN(im,2) + + # The fill, zscale, and zrange parameters determine the algorithms to + # be used to scale the image in the spatial and greyscale dimensions. + # If greyscale mapping is disabled the zscale and zrange options are + # disabled. Greyscale mapping can also be disabled by turning off + # zscale and zrange and setting Z1 and Z2 to the device greyscale min + # and max values, producing a unitary transformation. + + fill = clgetb ("fill") + call clgstr ("ztrans", Memc[ztrans], SZ_FNAME) + if (streq (Memc[ztrans], "none") || streq (Memc[ztrans], "user")) { + zscale_flag = false + zrange_flag = false + zmap_flag = false + } else { + zmap_flag = true + zscale_flag = clgetb ("zscale") + if (!zscale_flag) + zrange_flag = clgetb ("zrange") + } + + # Determine Z1 and Z2, the range of input greylevels to be mapped into + # the fixed range of display greylevels. + + if (zscale_flag) { + # Autoscaling is desired. Compute Z1 and Z2 which straddle the + # median computed by sampling a portion of the image. + + contrast = clgetr ("contrast") + nsample_lines = clgeti ("nsample_lines") + len_stdline = SAMPLE_SIZE / nsample_lines + call zscale (im, z1, z2, contrast, SAMPLE_SIZE, len_stdline) + + } else if (zrange_flag) { + nsample_lines = clgeti ("nsample_lines") + call maxmin (im, z1, z2, nsample_lines) + + } else if (zmap_flag) { + z1 = clgetr ("z1") + z2 = clgetr ("z2") + } + + # Determine the display window into which the image is to be mapped + # in normalized device coordinates. + + xcenter = max(0.0, min(1.0, clgetr ("xcenter"))) + ycenter = max(0.0, min(1.0, clgetr ("ycenter"))) + xsize = max(0.0, min(1.0, clgetr ("xsize"))) + ysize = max(0.0, min(1.0, clgetr ("ysize"))) + + # Determine X and Y scaling ratios required to map the image into the + # normalized display window. If spatial scaling is not desired filling + # must be disabled and XMAG and YMAG must be set to 1.0 in the + # parameter file. Fill mode will always produce an aspect ratio of 1; + # if nonequal scaling is required then the magnification ratios must + # be set explicitly by the user. + + if (fill) { + # Compute scale in units of window coords per data pixel required + # to scale image to fit window. + + xscale = xsize / max (1, (ncols - 1)) + yscale = ysize / max (1, (nlines - 1)) + + if (xscale < yscale) + yscale = xscale + else + xscale = yscale + + } else { + # Compute scale required to provide image magnification ratios + # specified by the user. Magnification is specified in units of + # display pixels, i.e, a magnification ratio of 1.0 means that + # image pixels will map to display pixels without scaling. + + xmag = clgetr ("xmag") + ymag = clgetr ("ymag") + xscale = 1.0 / ((cv_xres - 1) / xmag) + yscale = 1.0 / ((cv_yres - 1) / ymag) + } + + # Set device window limits in normalized device coordinates. + # World coord system 0 is used for the device window. + + w = W_WC(wdes,0) + W_XS(w) = xcenter - xsize / 2.0 + W_XE(w) = xcenter + xsize / 2.0 + W_YS(w) = ycenter - ysize / 2.0 + W_YE(w) = ycenter + ysize / 2.0 + + # Set pixel coordinates of window, world coordinate system #1. + + w = W_WC(wdes,1) + pxsize = xsize / xscale + pysize = ysize / yscale + + # If the image is too large to fit in the window given the scaling + # factors XSCALE and YSCALE, the following will set starting and ending + # pixel coordinates in the interior of the image. If the image is too + # small to fill the window then the pixel coords will reference beyond + # the bounds of the image. + + W_XS(w) = (ncols - 1) / 2.0 + 1 - (pxsize / 2.0) + W_XE(w) = W_XS(w) + pxsize + W_YS(w) = (nlines - 1) / 2.0 + 1 - (pysize / 2.0) + W_YE(w) = W_YS(w) + pysize + + # All spatial transformations are linear. + W_XT(w) = W_LINEAR + W_YT(w) = W_LINEAR + + # Determine whether a log or linear greyscale transformation is + # desired. + if (streq (Memc[ztrans], "log")) + W_ZT(w) = W_LOG + else if (streq (Memc[ztrans], "linear")) + W_ZT(w) = W_LINEAR + else if (streq (Memc[ztrans], "none")) + W_ZT(w) = W_UNITARY + else if (streq (Memc[ztrans], "user")) { + W_ZT(w) = W_USER + call salloc (lutfile, SZ_FNAME, TY_CHAR) + call clgstr ("lutfile", Memc[lutfile], SZ_FNAME) + call cv_ulut (Memc[lutfile], z1, z2, lut) + W_UPTR(w) = lut + } else { + call eprintf ("Bad greylevel transformation '%s'\n") + call pargstr (Memc[ztrans]) + W_ZT(w) = W_LINEAR + } + + # Set up the greyscale transformation. + W_ZS(w) = z1 + W_ZE(w) = z2 + + # Tell the user what values were used. + call printf ("cvl: z1 %6.1f, z2 %6.1f\n") + call pargr (z1) + call pargr (z2) + + # The user world coordinate system should be set from the CTRAN + # structure in the image header, but for now we just make it equal + # to the pixel coordinate system. + + call amovi (Memi[w], Memi[W_WC(wdes,2)], LEN_WC) +end diff --git a/pkg/images/tv/iis/src/load2.x b/pkg/images/tv/iis/src/load2.x new file mode 100644 index 00000000..5372907f --- /dev/null +++ b/pkg/images/tv/iis/src/load2.x @@ -0,0 +1,335 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +#### load2.x (from load.x) #### + +include <mach.h> +include <imset.h> +include <imhdr.h> +include <error.h> +include <gki.h> +include <fio.h> +include <fset.h> +include "gwindow.h" +include "../lib/ids.h" +include "cv.h" + +# DS_LOAD_DISPLAY -- Map an image into the display window. In general this +# involves independent linear transformations in the X, Y, and Z (greyscale) +# dimensions. If a spatial dimension is larger than the display window then +# the image is block averaged. If a spatial dimension or a block averaged +# dimension is smaller than the display window then linear interpolation is +# used to expand the image. Both the input image and the output device appear +# to us as images, accessed via IMIO. +# +# World coordinate system 0 (WCS 0) defines the position and size of the device +# window in NDC coordinates (0-1 in either axis). WCS 1 assigns a pixel +# coordinate system to the same window. If we convert the NDC coordinates of +# the window into device coordinates in pixels, then the ratios of the window +# coordinates in pixels to the image coordinates in pixels defines the real +# magnification factors for the two spatial axes. If the pixel coordinates +# are out of bounds then the image will be displayed centered in the window +# with zero fill at the edges. If the frame has not been erased then the fill +# areas must be explicitly zeroed. + +procedure ds_load_display (im, wdes, border_erase) + +pointer im # input image +pointer wdes # graphics window descriptor +bool border_erase + +int wx1, wx2, wy1, wy2 # device window to be filled with image data +real px1, px2, py1, py2 # image coords in fractional image pixels +real pxsize, pysize # size of image section in fractional pixels +real wxcenter, wycenter # center of device window in frac device pixels +real xmag, ymag # x,y magnification ratios +pointer w0, w1 # world coord systems 0 (NDC) and 1 (pixel) + +include "cv.com" + +begin + # Compute pointers to WCS 0 and 1. + w0 = W_WC(wdes,0) + w1 = W_WC(wdes,1) + + # Compute X and Y magnification ratios required to map image into + # the device window in device pixel units. + + xmag = (W_XE(w0) - W_XS(w0)) * cv_xres / (W_XE(w1) - W_XS(w1)) + ymag = (W_YE(w0) - W_YS(w0)) * cv_yres / (W_YE(w1) - W_YS(w1)) + + # Compute the coordinates of the image section to be displayed. + # This is not necessarily the same as WCS 1 since the WCS coords + # need not be inbounds. + + px1 = max (1.0, W_XS(w1)) + px2 = min (real (IM_LEN(im,1)), W_XE(w1)) + py1 = max (1.0, W_YS(w1)) + py2 = min (real (IM_LEN(im,2)), W_YE(w1)) + + # Now compute the coordinates of the image section to be written in + # device pixel units. This section must lie within or on the device + # window. + # This computation for I2S will give 257, which does differ by one + # for the Y center (due to inversion in I2S). This should not matter, + # but if it does, this comment will change! + + pxsize = px2 - px1 + pysize = py2 - py1 + wxcenter = (W_XE(w0) + W_XS(w0)) / 2.0 * cv_xres + 1 + wycenter = (W_YE(w0) + W_YS(w0)) / 2.0 * cv_yres + 1 + + wx1 = max (1, int (wxcenter - (pxsize / 2.0 * xmag))) + wx2 = max (wx1, min (cv_xres, int (wx1 + (pxsize * xmag)))) + wy1 = max (1, int (wycenter - (pysize / 2.0 * ymag))) + wy2 = max (wy1, min (cv_yres, int (wy1 + (pysize * ymag)))) + + # Display the image data, ignoring zero filling at the boundaries. + + call ds_map_image (im, px1,px2,py1,py2, wx1,wx2,wy1,wy2, + W_ZS(w1), W_ZE(w1), W_ZT(w1), W_UPTR(w1)) + + # Zero the border of the window if the frame has not been erased, + # and if the displayed section does not occupy the full window. + + if (border_erase) + call ds_erase_border (im, wdes, wx1,wx2,wy1,wy2) +end + + +# DS_MAP_IMAGE -- Map an image section from the input image to a section +# (window) of the output image (the display device). All spatial scaling is +# handled by the "scaled input" package, i.e., SIGL2[SR]. Our task is to +# get lines from the scaled input image, transform the greyscale if necessary, +# and write the lines to the output device. + +procedure ds_map_image (im, px1,px2,py1,py2, wx1,wx2,wy1,wy2, z1,z2,zt, uptr) + +pointer im # input image +real px1,px2,py1,py2 # input section +int wx1,wx2,wy1,wy2 # output section +real z1,z2 # range of input greylevels to be mapped. +int zt # log or linear greylevel transformation +pointer uptr # pointer to user transformation table + +bool unitary_greyscale_transformation +short lut1, lut2, z1_s, z2_s, dz1_s, dz2_s +real dz1, dz2 +int wy, nx, ny, xblk, yblk +pointer in, out, si +pointer sigl2s(), sigl2r(), sigl2_setup() +errchk sigl2s, sigl2r, sigl2_setup +real xs, xe, y +pointer sp, outr +bool fp_equalr() +real if_elogr() +extern if_elogr + +include "cv.com" + +begin + call smark (sp) + + # Set up for scaled image input. + + nx = wx2 - wx1 + 1 + ny = wy2 - wy1 + 1 + xblk = INDEFI + yblk = INDEFI + si = sigl2_setup (im, px1,px2,nx,xblk, py1,py2,ny,yblk) + + # Output array, and limiting x values in NDC + + call salloc (out, nx, TY_SHORT) + xs = real(wx1 - 1) * cv_xcon / GKI_MAXNDC + # Don't subtract 1 from wx2 as we want it to be first one not filled + xe = real(wx2) * cv_xcon / GKI_MAXNDC + if ( xe > 1.0) + xe = 1.0 + + # The device ZMIN and ZMAX parameters define the acceptable range + # of greyscale values for the output device (e.g., 0-255 for most 8-bit + # display devices). For the general display, we use 0 and the + # device "z" resolution. Values Z1 and Z2 are mapped linearly or + # logarithmically into these. + + dz1 = 0 + dz2 = cv_zres-1 + + # If the user specified the transfer function, see that the + # intensity and greyscale values are in range. + + if (zt == W_USER) { + call alims (Mems[uptr], SZ_BUF, lut1, lut2) + dz1_s = short (dz1) + dz2_s = short (dz2) + if (lut2 < dz1_s || lut1 > dz2_s) + call eprintf ("User specified greyscales out of range\n") + if (z2 < IM_MIN(im) || z1 > IM_MAX(im)) + call eprintf ("User specified intensities out of range\n") + } + + # Type short pixels are treated as a special case to minimize vector + # operations for such images (which are common). If the image pixels + # are either short or real then only the ALTR (greyscale transformation) + # vector operation is required. The ALTR operator linearly maps + # greylevels in the range Z1:Z2 to DZ1:DZ2, and does a floor ceiling + # of DZ1:DZ2 on all pixels outside the range. If unity mapping is + # employed the data is simply copied, i.e., floor ceiling constraints + # are not applied. This is very fast and will produce a contoured + # image on the display which will be adequate for some applications. + + if (zt == W_UNITARY) + unitary_greyscale_transformation = true + else + unitary_greyscale_transformation = + (fp_equalr (dz1,z1) && fp_equalr (dz2,z2)) || fp_equalr (z1,z2) + + if (IM_PIXTYPE(im) == TY_SHORT && zt != W_LOG) { + + # Set dz1_s and dz2_s depending on transformation + if (zt != W_USER) { + dz1_s = short (dz1) + dz2_s = short (dz2) + } else { + dz1_s = short (STARTPT) + dz2_s = short (ENDPT) + } + z1_s = short (z1) + z2_s = short (z2) + + for (wy=wy1; wy <= wy2; wy=wy+1) { + in = sigl2s (si, wy - wy1 + 1) + y = real(wy-1) * cv_ycon / GKI_MAXNDC + if (unitary_greyscale_transformation) + call gpcell (cv_gp, Mems[in], nx, 1, xs, y, xe, y) + else if (zt == W_USER) { + call amaps (Mems[in], Mems[out], nx, z1_s,z2_s, dz1_s,dz2_s) + call aluts (Mems[out], Mems[out], nx, Mems[uptr]) + call gpcell (cv_gp, Mems[out], nx, 1, xs, y, xe, y) + } else { + call amaps (Mems[in], Mems[out], nx, z1_s,z2_s, dz1_s,dz2_s) + call gpcell (cv_gp, Mems[out], nx, 1, xs, y, xe, y) + } + } + } else { + call salloc (outr, nx, TY_REAL) + for (wy=wy1; wy <= wy2; wy=wy+1) { + in = sigl2r (si, wy - wy1 + 1) + y = real(wy - 1) * cv_ycon / GKI_MAXNDC + + if (zt == W_LOG) { + call amapr (Memr[in], Memr[outr], nx, + z1, z2, 1.0, 10.0 ** MAXLOG) + call alogr (Memr[outr], Memr[outr], nx, if_elogr) + call amapr (Memr[outr], Memr[outr], nx, + 1.0, real(MAXLOG), dz1, dz2) + call achtrs (Memr[outr], Mems[out], nx) + } else if (unitary_greyscale_transformation) { + call achtrs (Memr[in], Mems[out], nx) + } else if (zt == W_USER) { + call amapr (Memr[in], Memr[outr], nx, z1,z2, STARTPT,ENDPT) + call achtrs (Memr[outr], Mems[out], nx) + call aluts (Mems[out], Mems[out], nx, Mems[uptr]) + } else { + call amapr (Memr[in], Memr[outr], nx, z1, z2, dz1, dz2) + call achtrs (Memr[outr], Mems[out], nx) + } + call gpcell (cv_gp, Mems[out], nx, 1, xs, y, xe, y) + } + } + + call sfree (sp) + call sigl2_free (si) +end + + +# DS_ERASE_BORDER -- Zero the border of the window if the frame has not been +# erased, and if the displayed section does not occupy the full window. +# It would be more efficient to do this while writing the greyscale data to +# the output image, but that would complicate the display procedures and frames +# are commonly erased before displaying an image. + +procedure ds_erase_border (im, wdes, wx1,wx2,wy1,wy2) + +pointer im # input image +pointer wdes # window descriptor +int wx1,wx2,wy1,wy2 # section of display window filled by image data + +int dx1,dx2,dy1,dy2 # coords of full display window in device pixels +int j, n, n1 +pointer w0 +pointer sp, zero +real xls, xle, xrs, xre, y + +include "cv.com" + +begin + call smark (sp) + call salloc (zero, cv_xres, TY_SHORT) + call aclrs (Mems[zero], cv_xres) + + # Compute device pixel coordinates of the full display window. + w0 = W_WC(wdes,0) + dx1 = W_XS(w0) * (cv_xres - 1) + 1 + dx2 = W_XE(w0) * (cv_xres - 1) + 1 + dy1 = W_YS(w0) * (cv_yres - 1) + 1 + dy2 = W_YE(w0) * (cv_yres - 1) + 1 + + # Determine left and right (exclusive), start and end, x values in NDC + # for pixels not already filled. + # If, say, dx1 < wx1, we want to clear dx1 through wx1-1, which means + # that for gpcell, we want the (right) end points to be the first + # pixel not cleared. + xls = real(dx1 - 1) * cv_xcon / GKI_MAXNDC + xle = real(wx1) * cv_xcon / GKI_MAXNDC + if (xle > 1.0) + xle = 1.0 + xre = real(dx2 - 1) * cv_xcon / GKI_MAXNDC + xrs = real(wx2) * cv_xcon / GKI_MAXNDC + if (xre > 1.0) + xre = 1.0 + + # Erase lower margin. + n = dx2 - dx1 + 1 + for (j=dy1; j < wy1; j=j+1) { + y = real(j-1) * cv_ycon / GKI_MAXNDC + call gpcell (cv_gp, Mems[zero], n, 1, xls, y, xre, y) + } + + # Erase left and right margins. By doing the right margin of a line + # immediately after the left margin we have a high liklihood that the + # display line will still be in the FIO buffer. + + n = wx1 - dx1 + n1 = dx2 - wx2 + for (j=wy1; j <= wy2; j=j+1) { + y = real(j-1) * cv_ycon / GKI_MAXNDC + if (dx1 < wx1) + call gpcell (cv_gp, Mems[zero], n, 1, xls, y, xle, y) + if (wx2 < dx2) + call gpcell (cv_gp, Mems[zero], n1, 1, xrs, y, xre, y) + } + + # Erase upper margin. + n = dx2 - dx1 + 1 + for (j=wy2+1; j <= dy2; j=j+1) { + y = real(j-1) * cv_ycon / GKI_MAXNDC + call gpcell (cv_gp, Mems[zero], n, 1, xls, y, xre, y) + } + + call sfree (sp) +end + + +# IF_ELOG -- The error function for log10. Note that MAX_EXPONENT is +# currently an integer so it is converted to the appropriate data type +# before being returned. + +real procedure if_elogr (x) + +real x # the input pixel value + +begin + return (real(-MAX_EXPONENT)) +end + diff --git a/pkg/images/tv/iis/src/map.x b/pkg/images/tv/iis/src/map.x new file mode 100644 index 00000000..5ea7c230 --- /dev/null +++ b/pkg/images/tv/iis/src/map.x @@ -0,0 +1,320 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include <gki.h> +include "../lib/ids.h" + +# MAP -- set fixed or variable LUT mapping + +procedure map(command) + +char command[ARB] + +char token[SZ_LINE] +int tok +short frames[IDS_MAXIMPL+2] # frames, graphics, EOD +short colors[IDS_MAXGCOLOR] +int device +short pcolor[2] +real limit +long seed +real urand(), xfactor +int ctoi() +int i, ip, iseed, level, nchar +bool triangle +pointer sp, rdata, gdata, bdata, rp, gp, bp + +include "cv.com" + +begin + # Find out if want to change output tables + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (( tok == TOK_IDENTIFIER) && (token[1] == 'o' )) { + device = IDS_OUTPUT_LUT + } else { + device = IDS_FRAME_LUT + # reset input pointers; same as having pushed back token + call reset_scan + call gargtok (tok, token, SZ_LINE) + } + + # Default to all frames, all colors + frames[1] = IDS_EOD + colors[1] = IDS_EOD + triangle = true # default to simple three function type + seed = -1 + level = 8 + + # which frames to change, colors, etc + + repeat { + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (tok == TOK_IDENTIFIER) { + if (token[1] == 'f') { + call cv_frame (token[2], frames) + if (frames[1] == ERR) + return + } else if (token[1] == 'c') { + call cv_color (token[2], colors) + if (colors[1] == ERR) + return + } else if (token[1] == 'r') { # (random) level count + ip = 2 + nchar = ctoi (token, ip, level) + if (nchar <= 0) { + call eprintf ("Incorrect random count: %s\n") + call pargstr (token[2]) + return + } + if (level < 4) + level = 4 + else if (level > 128) + level = 128 + triangle = false + } else if (token[1] == 's') { # seed + ip = 2 + nchar = ctoi (token, ip, iseed) + if (nchar <= 0) { + call eprintf ("Incorrect seed: %s\n") + call pargstr (token[2]) + return + } + seed = iseed + triangle = false + } else { + call eprintf ("Unknown map argument: %s\n") + call pargstr (token) + return + } + } else if (tok != TOK_NEWLINE) { + call eprintf ("Unexpected map input: %s\n") + call pargstr (token) + return + } + } until ( tok == TOK_NEWLINE) + + pcolor[2] = IDS_EOD + # Sorry, but we "know" that ofm shouldn't go beyond first + # 256 for common NOAO use. + if ( device == IDS_FRAME_LUT) + limit = 1.0 + else + limit = 0.25 + + # Build the three functions and load them. + # First, expand colors if using all + + if (colors[1] == IDS_EOD) { + colors[1] = IDS_RED + colors[2] = IDS_GREEN + colors[3] = IDS_BLUE + colors[4] = IDS_EOD + } + + # if standard pseudocolor, let kodak do it + + if (triangle) { + call kodak (device, frames, colors, limit) + return + } + + # Not standard pseudo color -- do random one + # First, set up arrays + + call smark (sp) + call salloc (rdata, level*4, TY_SHORT) + call salloc (gdata, level*4, TY_SHORT) + call salloc (bdata, level*4, TY_SHORT) + + if (seed == -1) + seed = level + + call aclrs (Mems[rdata], level*4) + call aclrs (Mems[gdata], level*4) + call aclrs (Mems[bdata], level*4) + + xfactor = real(GKI_MAXNDC)/level * limit + + # set first data points to zero (0,0) to (1/level,0) + Mems[rdata+2] = xfactor + Mems[gdata+2] = xfactor + Mems[bdata+2] = xfactor + # Set last segment to white ((level-1)/level,1.0) to (1.0,1.0) + Mems[rdata+level*4-4] = real(level-1) * xfactor + Mems[gdata+level*4-4] = real(level-1) * xfactor + Mems[bdata+level*4-4] = real(level-1) * xfactor + Mems[rdata+level*4-3] = GKI_MAXNDC + Mems[gdata+level*4-3] = GKI_MAXNDC + Mems[bdata+level*4-3] = GKI_MAXNDC + Mems[rdata+level*4-2] = GKI_MAXNDC + Mems[gdata+level*4-2] = GKI_MAXNDC + Mems[bdata+level*4-2] = GKI_MAXNDC + Mems[rdata+level*4-1] = GKI_MAXNDC + Mems[gdata+level*4-1] = GKI_MAXNDC + Mems[bdata+level*4-1] = GKI_MAXNDC + + # Do the intermediate ones + do i=2, level-1 { + rp = rdata + (i-1)*4 + gp = gdata + (i-1)*4 + bp = bdata + (i-1)*4 + Mems[rp] = real(i-1) * xfactor + Mems[gp] = real(i-1) * xfactor + Mems[bp] = real(i-1) * xfactor + Mems[rp+1] = urand(seed) * GKI_MAXNDC + Mems[gp+1] = urand(seed) * GKI_MAXNDC + Mems[bp+1] = urand(seed) * GKI_MAXNDC + Mems[rp+2] = real(i) * xfactor + Mems[gp+2] = real(i) * xfactor + Mems[bp+2] = real(i) * xfactor + Mems[rp+3] = Mems[rp+1] + Mems[gp+3] = Mems[gp+1] + Mems[bp+3] = Mems[bp+1] + } + + # If color requested, do it + for ( i = 1; colors[i] != IDS_EOD; i = i + 1 ) { + pcolor[1] = colors[i] + switch (colors[i]) { + case IDS_RED: + call cvwlut (device, frames, pcolor, Mems[rdata], level*4) + + case IDS_GREEN: + call cvwlut (device, frames, pcolor, Mems[gdata], level*4) + + case IDS_BLUE: + call cvwlut (device, frames, pcolor, Mems[bdata], level*4) + } + } + + call sfree (sp) +end + +# KODAK -- provides three variable width and variable center triangular +# color mapping functions. + +procedure kodak (device, frames, colors, limit) + +int device # IDS_FRAME_LUT or IDS_OUTPUT_LUT +short frames[ARB] # frames to change +short colors[ARB] # colors to affect +real limit # factor to apply to limit x range + +short wdata[20], pcolor[2] +real center, width +int n, ksub(), button, i +int cv_rdbut(), cv_wtbut() + +begin + pcolor[2] = IDS_EOD + for (i = 1; colors[i] != IDS_EOD; i = i + 1) { + pcolor[1] = colors[i] + switch (colors[i]) { + case IDS_RED: + n = ksub (1.0, 0.5, wdata, limit) + + case IDS_GREEN: + n = ksub (0.5, 0.5, wdata, limit) + + case IDS_BLUE: + n = ksub (0.0, 0.5, wdata, limit) + } + + call cvwlut (device, frames, pcolor, wdata, n) + } + + button = cv_rdbut() # clear buttons + repeat { + call eprintf ("Press A, B, C for red, green, blue; D to exit\n") + button = cv_wtbut() + if (button == 4) + break + switch (button) { + case 1: + pcolor[1] = IDS_RED + + case 2: + pcolor[1] = IDS_GREEN + + case 3: + pcolor[1] = IDS_BLUE + } + + # Loop, reading cursor and modifying the display for the + # selected color. + + repeat { + call cv_rcraw(center, width) + width = width * 2. # flatten it + n = ksub (center, width, wdata, limit) + call cvwlut (device, frames, pcolor, wdata, n) + button = cv_rdbut() + } until (button != 0) + } +end + +# KSUB -- determines data points for a triangular mapping function +# Returns number of points in data array. + +int procedure ksub (center, width, data, limit) + +real center, width, limit +short data[ARB] + +int n +real xs, xe, ys, ye, xscale + +include "cv.com" + +begin + n = 0 + xscale = GKI_MAXNDC * limit + if (width < (1.0/cv_yres)) + width = 1.0/cv_yres + + if (center > 0.) { + xs = center - width + if (xs < 0.) + xs = 0. + else if (xs > 0.) { + data[1] = 0. + data[2] = 0. + n = n + 2 + } + ys = (xs - center)/width + 1.0 + data[n+1] = xs * xscale + data[n+2] = ys * GKI_MAXNDC + data[n+3] = center * xscale + data[n+4] = GKI_MAXNDC + n = n + 4 + } + + if (center < 1.0) { + xe = width + center + if (xe > 1.0) + xe = 1.0 + ye = (center - xe)/width + 1.0 + data[n+1] = center * xscale + data[n+2] = GKI_MAXNDC + data[n+3] = xe * xscale + data[n+4] = ye * GKI_MAXNDC + n = n + 4 + if (xe < 1.0) { + data[n+1] = xscale + data[n+2] = 0 + n = n + 2 + } + } + + # Extend last value to end + if (limit != 1.0) { + data[n+1] = GKI_MAXNDC + data[n+2] = data[n] + n = n + 2 + } + + return (n) +end diff --git a/pkg/images/tv/iis/src/match.x b/pkg/images/tv/iis/src/match.x new file mode 100644 index 00000000..ebbe523d --- /dev/null +++ b/pkg/images/tv/iis/src/match.x @@ -0,0 +1,172 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include "../lib/ids.h" + +# MATCH -- Match look up tables. The command reads +# match this_one (to) that one + +procedure match + +char token[SZ_LINE] +int tok +short f_ref[2] +short c_ref[IDS_MAXGCOLOR+1] +short frames[IDS_MAXIMPL+1] +short colors[IDS_MAXGCOLOR+1] +short nextcolor +int nchar, i, val, ctoi() +int ltype + +include "cv.com" + +begin + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if ( (tok == TOK_IDENTIFIER) && (token[1] == 'o') ) { + ltype = IDS_OUTPUT_LUT + } else { + ltype = IDS_FRAME_LUT + # "Push back" the token + call reset_scan + call gargtok (tok, token, SZ_LINE) + } + + # All this parsing tells us why YACC and LEX were invented + # Use "i" to tell if have parsed something useful + + i = -1 + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if ((tok == TOK_IDENTIFIER) && (token[1] == 'f')) { + i = 1 + call cv_frame (token[2], frames) + if (frames[1] == ERR) + return + } else if (tok == TOK_NUMBER) { + i = 1 + nchar = ctoi (token, i, val) + if ((val < 1) || (val > cv_maxframes)) { + call eprintf ("Invalid frame specification: %d\n") + call pargi (val) + return + } else { + frames[1] = val + frames[2] = IDS_EOD + } + } else if (ltype == IDS_FRAME_LUT) { + call eprintf ("missing frame arguement\n") + return + } else + frames[1] = IDS_EOD + + # default first color argument to all colors for both FRAME and OUTPUT + # tables...means make all colors the same. + + colors[1] = IDS_EOD # default all colors + + # Advance if previous token was useful + + if ( i != -1 ) { + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + } + + # Look for a color + + if ((tok == TOK_IDENTIFIER) && (token[1] == 'c')) { + call cv_color (token[2], colors) + if (colors[1] == ERR) + return + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + } + + # look for fill word "to" + + if ((tok == TOK_IDENTIFIER) && (token[1] == 't')) { + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + } + + # if FRAME LUT, we default frame to first frame to be changed. + # if OUTPUT LUT, frame is irrelevant + + i = -1 + if (tok == TOK_IDENTIFIER) { + if (token[1] == 'f') + i = 2 + else if (token[1] != 'c') { + call eprintf ("Unexpected argument: %s\n") + call pargstr (token) + return + } + } else if (tok == TOK_NUMBER) + i = 1 + + # if ltype is OUTPUT lut, don't care about frame type, but can't + # omit it...so default to EOD + + f_ref[1] = IDS_EOD + f_ref[2] = IDS_EOD + if (ltype == IDS_FRAME_LUT) { + if (i == -1) { + f_ref[1] = frames[1] + } else { + nchar = ctoi (token, i, val) + if ((val < 1) || (val > cv_maxframes)) { + call eprintf ("Invalid frame specification: %d\n") + call pargi (val) + return + } + f_ref[1] = val + } + } + + # Only thing left should be the reference color. + # If found a frame before, advance the token. + + if (i != -1) { + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + } + if ((tok != TOK_NEWLINE) && (tok != TOK_IDENTIFIER)) { + call eprintf ("Unexpected input: %s\n") + call pargstr (token) + return + } + c_ref[1] = IDS_EOD + if (tok == TOK_IDENTIFIER) { + if (token[1] != 'c') { + call eprintf ("Unexpected input (color required): %s\n") + call pargstr (token) + return + } else { + call cv_color (token[2], c_ref) + if (c_ref[1] == ERR) + return + } + } + + if (c_ref[1] != IDS_EOD) + call cvmatch (ltype, f_ref, c_ref, frames, colors) + else { + # No specific color for reference. If no color specified + # to copy into, do all. + c_ref[2] = IDS_EOD + if ( colors[1] == IDS_EOD ) { + colors[1] = IDS_RED + colors[2] = IDS_GREEN + colors[3] = IDS_BLUE + colors[4] = IDS_EOD + } + # Match for each color given in "colors" + for ( i = 1 ; colors[i] != IDS_EOD; i = i + 1) { + nextcolor = colors[i+1] + colors[i+1] = IDS_EOD + c_ref[1] = colors[i] + call cvmatch (ltype, f_ref, c_ref, frames, colors[i]) + colors[i+1] = nextcolor + } + } +end diff --git a/pkg/images/tv/iis/src/maxmin.x b/pkg/images/tv/iis/src/maxmin.x new file mode 100644 index 00000000..d16874e9 --- /dev/null +++ b/pkg/images/tv/iis/src/maxmin.x @@ -0,0 +1,52 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <imhdr.h> + +# MAXMIN -- Get the minimum and maximum pixel values of an image. If valid +# header values are available they are used, otherwise the image is sampled +# on an even grid and the min and max values of this sample are returned. + +procedure maxmin (im, zmin, zmax, nsample_lines) + +pointer im +real zmin, zmax # min and max intensity values +int nsample_lines # amount of image to sample + +int step, ncols, nlines, sample_size, imlines, i +real minval, maxval +pointer imgl2r() + +begin + # Only calculate minimum, maximum pixel values if the current + # values are unknown, or if the image was modified since the + # old values were computed. + + ncols = IM_LEN(im,1) + nlines = IM_LEN(im,2) + + if (IM_LIMTIME(im) >= IM_MTIME(im)) { + # Use min and max values in image header if they are up to date. + zmin = IM_MIN(im) + zmax = IM_MAX(im) + + } else { + zmin = MAX_REAL + zmax = -MAX_REAL + + # Try to include a constant number of pixels in the sample + # regardless of the image size. The entire image is used if we + # have a small image, and at least sample_lines lines are read + # if we have a large image. + + sample_size = 512 * nsample_lines + imlines = min(nlines, max(nsample_lines, sample_size / ncols)) + step = nlines / (imlines + 1) + + do i = 1 + step, nlines, max (1, step) { + call alimr (Memr[imgl2r(im,i)], ncols, minval, maxval) + zmin = min (zmin, minval) + zmax = max (zmax, maxval) + } + } +end diff --git a/pkg/images/tv/iis/src/mkpkg b/pkg/images/tv/iis/src/mkpkg new file mode 100644 index 00000000..34ee515c --- /dev/null +++ b/pkg/images/tv/iis/src/mkpkg @@ -0,0 +1,39 @@ +# Make the CV display load and control package. + +$checkout libpkg.a ../ +$update libpkg.a +$checkin libpkg.a ../ +$exit + +libpkg.a: + blink.x ../lib/ids.h <ctotok.h> <ctype.h> <gki.h> cv.com + clear.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com + cv.x cv.com cv.h ../lib/ids.h <ctotok.h> <error.h> <fio.h>\ + <fset.h> <gki.h> + cvparse.x cv.com ../lib/ids.h <ctype.h> + cvulut.x cv.h <ctype.h> <error.h> + cvutil.x cv.com cv.h ../lib/ids.h <gki.h> <gset.h> <imhdr.h>\ + cv.com + display.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com + load1.x cv.com cv.h ../lib/ids.h <error.h> <gki.h> gwindow.h\ + <fio.h> <fset.h> <imhdr.h> <imset.h> <mach.h> + load2.x cv.com cv.h ../lib/ids.h <error.h> <gki.h> gwindow.h\ + cv.com <fio.h> <fset.h> <imhdr.h> <imset.h> <mach.h> + map.x ../lib/ids.h <ctotok.h> <ctype.h> <gki.h> cv.com + match.x ../lib/ids.h <ctotok.h> cv.com + maxmin.x <imhdr.h> <mach.h> + offset.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com + pan.x cv.com ../lib/ids.h <ctotok.h> <ctype.h> <gki.h> + range.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com + rdcur.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com <gki.h> + reset.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com + sigl2.x <error.h> <imhdr.h> + snap.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com <gki.h>\ + <imhdr.h> + split.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com + tell.x ../lib/ids.h cv.com + text.x ../lib/ids.h <ctotok.h> <ctype.h> + window.x ../lib/ids.h <ctotok.h> <ctype.h> <gki.h> cv.com + zoom.x ../lib/ids.h <ctotok.h> <ctype.h> <gki.h> cv.com + zscale.x <imhdr.h> + ; diff --git a/pkg/images/tv/iis/src/offset.x b/pkg/images/tv/iis/src/offset.x new file mode 100644 index 00000000..356ae55f --- /dev/null +++ b/pkg/images/tv/iis/src/offset.x @@ -0,0 +1,53 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include "../lib/ids.h" + +# OFFSET -- Change the bias (offset) for certain colors + +procedure offset() + +int tok, i, nchar, ip +char token[SZ_LINE] +short color[IDS_MAXGCOLOR+1] +short offsetdata[4] # extra space for cvmove EOD +int count, ctoi() + +include "cv.com" + +begin + # In principle, we should be able to accept input for color group + # followed by offset value(s) or "vice versa" or for a series of + # color/offset pairs. We try for most of that. + color[1] = ERR + offsetdata[1] = ERR + count = 1 + # anything but TOK_NEWLINE + tok = TOK_NUMBER + repeat { + if (tok == TOK_NEWLINE) { + call eprintf ("Insufficient offset specification\n") + return + } + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (token[1] == 'c') { + call cv_color (token[2], color) + if (color[1] == ERR) + return + } else if (tok == TOK_NUMBER) { + ip = 1 + nchar = ctoi (token, ip, i) + if ( count <= 3) { + offsetdata[count] = i + count = count + 1 + } + } + } until ( (color[1] != ERR) && (offsetdata[1] != ERR) && + (tok == TOK_NEWLINE) ) + + offsetdata[count] = IDS_EOD # mark end + + call cvoffset (color, offsetdata) +end diff --git a/pkg/images/tv/iis/src/pan.x b/pkg/images/tv/iis/src/pan.x new file mode 100644 index 00000000..b8929510 --- /dev/null +++ b/pkg/images/tv/iis/src/pan.x @@ -0,0 +1,99 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include <gki.h> +include "../lib/ids.h" + +# PAN -- pan some or all of the frames + +procedure pan() + +char token[SZ_LINE] +int tok +short frames[IDS_MAXIMPL+2] # frames, graphics, EOD + +include "cv.com" + +begin + frames[1] = IDS_EOD # default all frames + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (token[1] == 'f') { + call cv_frame (token[2], frames) + if (frames[1] == ERR) + return + } else if (tok == TOK_NUMBER) { + call cv_frame (token[1], frames) + if (frames[1] == ERR) + return + } else { + call eprintf ("Unexpected input: %s\n") + call pargstr (token) + return + } + + call pansub (frames) +end + + +# PANSUB -- Pan subroutine, handles code common to pan and zoom + +procedure pansub (frames) + +short frames[ARB] # frames to pan + +int button +int cnum, cv_rdbut() +real x,y, xc, yc +real oldx, oldy + +include "cv.com" + +begin + button = cv_rdbut() # clear buttons by reading them + call eprintf ("Press any button when done\n") + + # Where is cursor now? + + call cv_rcraw (xc,yc) + + # Calculate NDC screen center and cursor number. + # x,y are NDC, but always < 1.0 The transformation applied here + # insures that the correct pixel is calculated by the kernel + # after passing x,y through the gio cursor routines. + x = real(cv_xcen - 1) * cv_xcon / GKI_MAXNDC + y = real(cv_ycen - 1) * cv_ycon / GKI_MAXNDC + cnum = frames[1] + if (cnum == IDS_EOD) + cnum = 0 + call cv_scraw (x, y) # put cursor at screen center + + # Determine NDC there for frame of interest + call cv_rcur (cnum, x, y) + + # Restore cursor + call cv_scraw (xc, yc) + + repeat { + oldx = xc + oldy = yc + repeat { + call cv_rcraw (xc, yc) + button = cv_rdbut() + } until ( (xc != oldx) || (yc != oldy) || (button > 0)) + # Determine change and reflect it about current screen + # center so image moves in direction cursor moves. + x = x - (xc - oldx) + y = y - (yc - oldy) + if (x > 1.0) + x = x - 1.0 + else if (x < 0) + x = x + 1.0 + if (y > 1.0) + y = y - 1.0 + else if (y < 0) + y = y + 1.0 + call cvpan (frames, x, y) + } until (button > 0) +end diff --git a/pkg/images/tv/iis/src/range.x b/pkg/images/tv/iis/src/range.x new file mode 100644 index 00000000..664e3ab8 --- /dev/null +++ b/pkg/images/tv/iis/src/range.x @@ -0,0 +1,57 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include "../lib/ids.h" + +# RANGE -- set the scaling (range) registers + +procedure range() + +char token[SZ_LINE] +int tok, i, nchar, ip +short color[IDS_MAXGCOLOR+1] +short rdata[4] # extra space for cvmove EOD +int count, ctoi() + +include "cv.com" + +begin + # In principle, we should be able to accept input for color group + # followed by range value(s) or "vice versa" or for a series of + # color/range pairs. We try for most of that. + color[1] = IDS_EOD + rdata[1] = ERR + count = 1 + # anything but TOK_NEWLINE + tok = TOK_NUMBER + repeat { + if (tok == TOK_NEWLINE) { + call eprintf ("Insufficient range specification\n") + return + } + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (token[1] == 'c') { + call cv_color (token[2], color) + if (color[1] == ERR) + return + } else if (tok == TOK_NUMBER) { + ip = 1 + nchar = ctoi (token, ip, i) + if (i < 1) { + call eprintf ("bad range specification: %d\n") + call pargi (i) + return + } + if ( count <= 3) { + rdata[count] = i + count = count + 1 + } + } + } until ( (rdata[1] != ERR) && (tok == TOK_NEWLINE )) + + rdata[count] = IDS_EOD # mark end + + call cvrange ( color, rdata) +end diff --git a/pkg/images/tv/iis/src/rdcur.x b/pkg/images/tv/iis/src/rdcur.x new file mode 100644 index 00000000..5d27097e --- /dev/null +++ b/pkg/images/tv/iis/src/rdcur.x @@ -0,0 +1,111 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include <gki.h> +include "../lib/ids.h" + +# RDCUR -- read cursor and datum + +procedure rdcur() + +char token[SZ_LINE], ch +int tok, cnum, px, py +int junk, ip, fx, fy +real x,y +short datum +short frames[IDS_MAXIMPL+2] # frames, one graphics, EOD +int scan(), ctoi(), mod(), and() + +include "cv.com" + +begin + cnum = ERR + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (tok == TOK_NUMBER) { + ip = 1 + junk = ctoi (token, ip, cnum) + frames[1] = cnum + frames[2] = IDS_EOD + } + else if (tok == TOK_IDENTIFIER) { + if (token[1] == 'o') { + if (token[2] == 'n') + call cvcur(IDS_ON) + else if (token[2] == 'f') + call cvcur(IDS_OFF) + else { + call eprintf ("Unrecognized cursor command: %s\n") + call pargstr (token) + } + return + } + call cv_frame (token[2], frames) + cnum = frames[1] + if ( cnum == IDS_EOD) { + call eprintf ("Please specify a particular frame\n") + return + } + } + if ( (cnum == ERR) || (cnum < 1) ) { + call eprintf ("bad cursor number: %d\n") + call pargi (cnum) + return + } + + # set kernel to do i/o on specified frames (for ggcell routine) + call cv_iset (frames) + + call eprintf ("Press <cr> for each read; any key but <sp>, and then <cr>, to exit\n") + repeat { + if (scan() != EOS) + break + repeat { + call scanc (ch) + } until (ch != ' ') + if (ch != '\n') + break + call cv_rcur (cnum, x, y) + call ggcell (cv_gp, datum, 1, 1, x, y, x, y) + x = x * GKI_MAXNDC / cv_xcon + 1. + y = y * GKI_MAXNDC / cv_ycon + 1. + px = int(x) + py = int(y) + # Only allow fractions to 1/8 as that is max zoom for IIS + x = real (int((x - px)*8))/8. + y = real (int((y - py)*8))/8. + # Print minimum number of decimal places, but do x and y the same + call eprintf ("frame %d, pixel (") + call pargi (cnum) + fx = x * 8 + fy = y * 8 + if ((fx == 0) && (fy == 0)) { + call eprintf ("%d,%d") + call pargi (px) + call pargi (py) + junk = 0 + } else { + call eprintf ("%.*f,%.*f") + + if ( (mod(fx,4) == 0) && (mod(fy,4) == 0) ) + junk = 1 + else if ( (and(fx,1) != 0) || (and(fy,1) != 0) ) + junk = 3 + else + junk = 2 + + call pargi (junk) + call pargr (px+x) + call pargi (junk) + call pargr (py+y) + } + if (junk == 0) + junk = 8 + else + junk = 6 - 2 * junk + call eprintf ("): %*w%4d\n") + call pargi (junk) + call pargs (datum) + } +end diff --git a/pkg/images/tv/iis/src/reset.x b/pkg/images/tv/iis/src/reset.x new file mode 100644 index 00000000..3a2e60e9 --- /dev/null +++ b/pkg/images/tv/iis/src/reset.x @@ -0,0 +1,37 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include "../lib/ids.h" + +# RESET -- reset the display + +procedure reset() + +char token[SZ_LINE] +int tok + +include "cv.com" + +begin + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (tok == TOK_IDENTIFIER) { + switch(token[1]) { + case 'r': + call cvreset( IDS_R_SOFT) + + case 't': + call cvreset( IDS_R_MEDIUM) + + case 'i': + call cvreset( IDS_R_HARD) + + case 'a': + call cvreset( IDS_R_SOFT) + call cvreset( IDS_R_MEDIUM) + call cvreset( IDS_R_HARD) + + } + } +end diff --git a/pkg/images/tv/iis/src/sigl2.x b/pkg/images/tv/iis/src/sigl2.x new file mode 100644 index 00000000..226d4f5b --- /dev/null +++ b/pkg/images/tv/iis/src/sigl2.x @@ -0,0 +1,677 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <imhdr.h> +include <error.h> + +.help sigl2, sigl2_setup +.nf ___________________________________________________________________________ +SIGL2 -- Get a line from a spatially scaled 2-dimensional image. This procedure +works like the regular IMIO get line procedure, but rescales the input +2-dimensional image in either or both axes upon input. If the magnification +ratio required is greater than 0 and less than 2 then linear interpolation is +used to resample the image. If the magnification ratio is greater than or +equal to 2 then the image is block averaged by the smallest factor which +reduces the magnification to the range 0-2 and then interpolated back up to +the desired size. In some cases this will smooth the data slightly, but the +operation is efficient and avoids aliasing effects. + + si = sigl2_setup (im, x1,x2,nx, y1,y2,ny) + sigl2_free (si) + ptr = sigl2[sr] (si, linenumber) + +SIGL2_SETUP must be called to set up the transformations after mapping the +image and before performing any scaled i/o to the image. SIGL2_FREE must be +called when finished to return buffer space. +.endhelp ______________________________________________________________________ + +# Scaled image descriptor for 2-dim images + +define SI_LEN 15 +define SI_MAXDIM 2 # images of 2 dimensions supported +define SI_NBUFS 3 # nbuffers used by SIGL2 + +define SI_IM Memi[$1] # pointer to input image header +define SI_GRID Memi[$1+1+$2-1] # pointer to array of X coords +define SI_NPIX Memi[$1+3+$2-1] # number of X coords +define SI_BAVG Memi[$1+5+$2-1] # X block averaging factor +define SI_INTERP Memi[$1+7+$2-1] # interpolate X axis +define SI_BUF Memi[$1+9+$2-1] # line buffers +define SI_TYBUF Memi[$1+12] # buffer type +define SI_XOFF Memi[$1+13] # offset in input image to first X +define SI_INIT Memi[$1+14] # YES until first i/o is done + +define OUTBUF SI_BUF($1,3) + +define SI_TOL (1E-5) # close to a pixel +define INTVAL (abs ($1 - nint($1)) < SI_TOL) +define SWAPI {tempi=$2;$2=$1;$1=tempi} +define SWAPP {tempp=$2;$2=$1;$1=tempp} +define NOTSET (-9999) + +# SIGL2_SETUP -- Set up the spatial transformation for SIGL2[SR]. Compute +# the block averaging factors (1 if no block averaging is required) and +# the sampling grid points, i.e., pixel coordinates of the output pixels in +# the input image. +# +# Valdes - Jan 9, 1985: +# Nx or ny can be 1 and blocking factors can be specified. + +pointer procedure sigl2_setup (im, px1, px2, nx, xblk, py1, py2, ny, yblk) + +pointer im # the input image +real px1, px2 # range in X to be sampled on an even grid +int nx # number of output pixels in X +int xblk # blocking factor in x +real py1, py2 # range in Y to be sampled on an even grid +int ny # number of output pixels in Y +int yblk # blocking factor in y + +int npix, noldpix, nbavpix, i, j +int npts[SI_MAXDIM] # number of output points for axis +int blksize[SI_MAXDIM] # block averaging factor (npix per block) +real tau[SI_MAXDIM] # tau = p(i+1) - p(i) in fractional pixels +real p1[SI_MAXDIM] # starting pixel coords in each axis +real p2[SI_MAXDIM] # ending pixel coords in each axis +real scalar, start +pointer si, gp + +begin + iferr (call calloc (si, SI_LEN, TY_STRUCT)) + call erract (EA_FATAL) + + SI_IM(si) = im + SI_NPIX(si,1) = nx + SI_NPIX(si,2) = ny + SI_INIT(si) = YES + + p1[1] = px1 # X = index 1 + p2[1] = px2 + npts[1] = nx + blksize[1] = xblk + + p1[2] = py1 # Y = index 2 + p2[2] = py2 + npts[2] = ny + blksize[2] = yblk + + # Compute block averaging factors if not defined. + # If there is only one pixel then the block average is the average + # between the first and last point. + + do i = 1, SI_MAXDIM { + if ((blksize[i] >= 1) && !IS_INDEFI (blksize[i])) { + if (npts[i] == 1) + tau[i] = 0. + else + tau[i] = (p2[i] - p1[i]) / (npts[i] - 1) + } else { + if (npts[i] == 1) { + tau[i] = 0. + blksize[i] = int (p2[i] - p1[i] + 1) + } else { + tau[i] = (p2[i] - p1[i]) / (npts[i] - 1) + if (tau[i] >= 2.0) { + + # If nx or ny is not an integral multiple of the block + # averaging factor, noldpix is the next larger number + # which is an integral multiple. When the image is + # block averaged pixels will be replicated as necessary + # to fill the last block out to this size. + + blksize[i] = int (tau[i]) + npix = p2[i] - p1[i] + 1 + noldpix = (npix+blksize[i]-1) / blksize[i] * blksize[i] + nbavpix = noldpix / blksize[i] + scalar = real (nbavpix - 1) / real (noldpix - 1) + p1[i] = (p1[i] - 1.0) * scalar + 1.0 + p2[i] = (p2[i] - 1.0) * scalar + 1.0 + tau[i] = (p2[i] - p1[i]) / (npts[i] - 1) + } else + blksize[i] = 1 + } + } + } + + SI_BAVG(si,1) = blksize[1] + SI_BAVG(si,2) = blksize[2] + + if (IS_INDEFI (xblk)) + xblk = blksize[1] + if (IS_INDEFI (yblk)) + yblk = blksize[2] + + # Allocate and initialize the grid arrays, specifying the X and Y + # coordinates of each pixel in the output image, in units of pixels + # in the input (possibly block averaged) image. + + do i = 1, SI_MAXDIM { + # The X coordinate is special. We do not want to read entire + # input image lines if only a range of input X values are needed. + # Since the X grid vector passed to ALUI (the interpolator) must + # contain explicit offsets into the vector being interpolated, + # we must generate interpolator grid points starting near 1.0. + # The X origin, used to read the block averaged input line, is + # given by XOFF. + + if (i == 1) { + SI_XOFF(si) = int (p1[i]) + start = p1[1] - int (p1[i]) + 1.0 + } else + start = p1[i] + + # Do the axes need to be interpolated? + if (INTVAL(start) && INTVAL(tau[i])) + SI_INTERP(si,i) = NO + else + SI_INTERP(si,i) = YES + + # Allocate grid buffer and set the grid points. + iferr (call malloc (gp, npts[i], TY_REAL)) + call erract (EA_FATAL) + SI_GRID(si,i) = gp + do j = 0, npts[i]-1 + Memr[gp+j] = start + (j * tau[i]) + } + + return (si) +end + + +# SIGL2_FREE -- Free storage associated with an image opened for scaled +# input. This does not close and unmap the image. + +procedure sigl2_free (si) + +pointer si +int i + +begin + # Free SIGL2 buffers. + do i = 1, SI_NBUFS + if (SI_BUF(si,i) != NULL) + call mfree (SI_BUF(si,i), SI_TYBUF(si)) + + # Free GRID buffers. + do i = 1, SI_MAXDIM + if (SI_GRID(si,i) != NULL) + call mfree (SI_GRID(si,i), TY_REAL) + + call mfree (si, TY_STRUCT) +end + + +# SIGL2S -- Get a line of type short from a scaled image. Block averaging is +# done by a subprocedure; this procedure gets a line from a possibly block +# averaged image and if necessary interpolates it to the grid points of the +# output line. + +pointer procedure sigl2s (si, lineno) + +pointer si # pointer to SI descriptor +int lineno + +pointer rawline, tempp, gp +int i, buf_y[2], new_y[2], tempi, curbuf, altbuf +int npix, nblks_y, ybavg, x1, x2 +real x, y, weight_1, weight_2 +pointer si_blkavgs() +errchk si_blkavgs + +begin + npix = SI_NPIX(si,1) + + # Determine the range of X (in pixels on the block averaged input image) + # required for the interpolator. + + gp = SI_GRID(si,1) + x1 = SI_XOFF(si) + x = Memr[gp+npix-1] + x2 = x1 + int(x) + if (INTVAL(x)) + x2 = x2 - 1 + x2 = max (x1 + 1, x2) + + gp = SI_GRID(si,2) + y = Memr[gp+lineno-1] + + # The following is an optimization provided for the case when it is + # not necessary to interpolate in either X or Y. Block averaging is + # permitted. + + if (SI_INTERP(si,1) == NO && SI_INTERP(si,2) == NO) + return (si_blkavgs (SI_IM(si), x1, x2, int(y), + SI_BAVG(si,1), SI_BAVG(si,2))) + + # If we are interpolating in Y two buffers are required, one for each + # of the two input image lines required to interpolate in Y. The lines + # stored in these buffers are interpolated in X to the output grid but + # not in Y. Both buffers are not required if we are not interpolating + # in Y, but we use them anyhow to simplify the code. + + if (SI_INIT(si) == YES) { + do i = 1, 2 { + if (SI_BUF(si,i) != NULL) + call mfree (SI_BUF(si,i), SI_TYBUF(si)) + call malloc (SI_BUF(si,i), npix, TY_SHORT) + SI_TYBUF(si) = TY_SHORT + buf_y[i] = NOTSET + } + if (OUTBUF(si) != NULL) + call mfree (OUTBUF(si), SI_TYBUF(si)) + call malloc (OUTBUF(si), npix, TY_SHORT) + SI_INIT(si) = NO + } + + # If the Y value of the new line is not in range of the contents of the + # current line buffers, refill one or both buffers. To refill we must + # read a (possibly block averaged) input line and interpolate it onto + # the X grid. The X and Y values herein are in the coordinate system + # of the (possibly block averaged) input image. + + new_y[1] = int(y) + new_y[2] = int(y) + 1 + + # Get the pair of lines whose integral Y values form an interval + # containing the fractional Y value of the output line. Sometimes the + # desired line will happen to be in the other buffer already, in which + # case we just have to swap buffers. Often the new line will be the + # current line, in which case nothing is done. This latter case occurs + # frequently when the magnification ratio is large. + + curbuf = 1 + altbuf = 2 + + do i = 1, 2 { + if (new_y[i] == buf_y[i]) { + ; + } else if (new_y[i] == buf_y[altbuf]) { + SWAPP (SI_BUF(si,1), SI_BUF(si,2)) + SWAPI (buf_y[1], buf_y[2]) + + } else { + # Get line and interpolate onto output grid. If interpolation + # is not required merely copy data out. This code is set up + # to always use two buffers; in effect, there is one buffer of + # look ahead, even when Y[i] is integral. This means that we + # will go out of bounds by one line at the top of the image. + # This is handled by copying the last line. + + ybavg = SI_BAVG(si,2) + nblks_y = (IM_LEN (SI_IM(si), 2) + ybavg-1) / ybavg + if (new_y[i] <= nblks_y) + rawline = si_blkavgs (SI_IM(si), x1, x2, new_y[i], + SI_BAVG(si,1), SI_BAVG(si,2)) + + if (SI_INTERP(si,1) == NO) + call amovs (Mems[rawline], Mems[SI_BUF(si,i)], npix) + else { + call aluis (Mems[rawline], Mems[SI_BUF(si,i)], + Memr[SI_GRID(si,1)], npix) + } + + buf_y[i] = new_y[i] + } + + SWAPI (altbuf, curbuf) + } + + # We now have two line buffers straddling the output Y value, + # interpolated to the X grid of the output line. To complete the + # bilinear interpolation operation we take a weighted sum of the two + # lines. If the range from buf_y[1] to buf_y[2] is repeatedly + # interpolated in Y no additional i/o occurs and the linear + # interpolation operation (ALUI) does not have to be repeated (only the + # weighted sum is required). If the distance of Y from one of the + # buffers is zero then we do not even have to take a weighted sum. + # This is not unusual because we may be called with a magnification + # of 1.0 in Y. + + weight_1 = 1.0 - (y - buf_y[1]) + weight_2 = 1.0 - weight_1 + + if (weight_2 < SI_TOL) + return (SI_BUF(si,1)) + else if (weight_1 < SI_TOL) + return (SI_BUF(si,2)) + else { + call awsus (Mems[SI_BUF(si,1)], Mems[SI_BUF(si,2)], + Mems[OUTBUF(si)], npix, weight_1, weight_2) + return (OUTBUF(si)) + } +end + + +# SI_BLKAVGS -- Get a line from a block averaged image of type short. +# For example, block averaging by a factor of 2 means that pixels 1 and 2 +# are averaged to produce the first output pixel, 3 and 4 are averaged to +# produce the second output pixel, and so on. If the length of an axis +# is not an integral multiple of the block size then the last pixel in the +# last block will be replicated to fill out the block; the average is still +# defined even if a block is not full. + +pointer procedure si_blkavgs (im, x1, x2, y, xbavg, ybavg) + +pointer im # input image +int x1, x2 # range of x blocks to be read +int y # y block to be read +int xbavg, ybavg # X and Y block averaging factors + +short temp_s +int nblks_x, nblks_y, ncols, nlines, xoff, i, j +int first_line, nlines_in_sum, npix, nfull_blks, count +real sum +pointer sp, a, b +pointer imgs2s() +errchk imgs2s + +begin + call smark (sp) + + ncols = IM_LEN(im,1) + nlines = IM_LEN(im,2) + xoff = (x1 - 1) * xbavg + 1 + npix = min (ncols, xoff + (x2 - x1 + 1) * xbavg - 1) + + if ((xbavg < 1) || (ybavg < 1)) + call error (1, "si_blkavg: illegal block size") + else if (x1 < 1 || x2 > ncols) + call error (2, "si_blkavg: column index out of bounds") + else if ((xbavg == 1) && (ybavg == 1)) + return (imgs2s (im, xoff, xoff + npix - 1, y, y)) + + nblks_x = (npix + xbavg-1) / xbavg + nblks_y = (nlines + ybavg-1) / ybavg + + if (y < 1 || y > nblks_y) + call error (2, "si_blkavg: block number out of range") + + call salloc (b, nblks_x, TY_SHORT) + + if (ybavg > 1) { + call aclrs (Mems[b], nblks_x) + nlines_in_sum = 0 + } + + # Read and accumulate all input lines in the block. + first_line = (y - 1) * ybavg + 1 + + do i = first_line, min (nlines, first_line + ybavg - 1) { + # Get line from input image. + a = imgs2s (im, xoff, xoff + npix - 1, i, i) + + # Block average line in X. + if (xbavg > 1) { + # First block average only the full blocks. + nfull_blks = npix / xbavg + call abavs (Mems[a], Mems[a], nfull_blks, xbavg) + + # Now average the final partial block, if any. + if (nfull_blks < nblks_x) { + sum = 0.0 + count = 0 + do j = nfull_blks * xbavg + 1, npix { + sum = sum + Mems[a+j-1] + count = count + 1 + } + Mems[a+nblks_x-1] = sum / count + } + } + + # Add line into block sum. Keep track of number of lines in sum + # so that we can compute block average later. + if (ybavg > 1) { + call aadds (Mems[a], Mems[b], Mems[b], nblks_x) + nlines_in_sum = nlines_in_sum + 1 + } + } + + # Compute the block average in Y from the sum of all lines block + # averaged in X. Overwrite buffer A, the buffer returned by IMIO. + # This is kosher because the block averaged line is never longer + # than an input line. + + if (ybavg > 1) { + temp_s = nlines_in_sum + call adivks (Mems[b], temp_s, Mems[a], nblks_x) + } + + call sfree (sp) + return (a) +end + + +# SIGL2R -- Get a line of type real from a scaled image. Block averaging is +# done by a subprocedure; this procedure gets a line from a possibly block +# averaged image and if necessary interpolates it to the grid points of the +# output line. + +pointer procedure sigl2r (si, lineno) + +pointer si # pointer to SI descriptor +int lineno + +pointer rawline, tempp, gp +int i, buf_y[2], new_y[2], tempi, curbuf, altbuf +int npix, nblks_y, ybavg, x1, x2 +real x, y, weight_1, weight_2 +pointer si_blkavgr() +errchk si_blkavgr + +begin + npix = SI_NPIX(si,1) + + # Deterine the range of X (in pixels on the block averaged input image) + # required for the interpolator. + + gp = SI_GRID(si,1) + x1 = SI_XOFF(si) + x = Memr[gp+npix-1] + x2 = x1 + int(x) + if (INTVAL(x)) + x2 = x2 - 1 + x2 = max (x1 + 1, x2) + + gp = SI_GRID(si,2) + y = Memr[gp+lineno-1] + + # The following is an optimization provided for the case when it is + # not necessary to interpolate in either X or Y. Block averaging is + # permitted. + + if (SI_INTERP(si,1) == NO && SI_INTERP(si,2) == NO) + return (si_blkavgr (SI_IM(si), x1, x2, int(y), + SI_BAVG(si,1), SI_BAVG(si,2))) + + # If we are interpolating in Y two buffers are required, one for each + # of the two input image lines required to interpolate in Y. The lines + # stored in these buffers are interpolated in X to the output grid but + # not in Y. Both buffers are not required if we are not interpolating + # in Y, but we use them anyhow to simplify the code. + + if (SI_INIT(si) == YES) { + do i = 1, 2 { + if (SI_BUF(si,i) != NULL) + call mfree (SI_BUF(si,i), SI_TYBUF(si)) + call malloc (SI_BUF(si,i), npix, TY_REAL) + SI_TYBUF(si) = TY_REAL + buf_y[i] = NOTSET + } + if (OUTBUF(si) != NULL) + call mfree (OUTBUF(si), SI_TYBUF(si)) + call malloc (OUTBUF(si), npix, TY_REAL) + SI_INIT(si) = NO + } + + # If the Y value of the new line is not in range of the contents of the + # current line buffers, refill one or both buffers. To refill we must + # read a (possibly block averaged) input line and interpolate it onto + # the X grid. The X and Y values herein are in the coordinate system + # of the (possibly block averaged) input image. + + new_y[1] = int(y) + new_y[2] = int(y) + 1 + + # Get the pair of lines whose integral Y values form an interval + # containing the fractional Y value of the output line. Sometimes the + # desired line will happen to be in the other buffer already, in which + # case we just have to swap buffers. Often the new line will be the + # current line, in which case nothing is done. This latter case occurs + # frequently when the magnification ratio is large. + + curbuf = 1 + altbuf = 2 + + do i = 1, 2 { + if (new_y[i] == buf_y[i]) { + ; + } else if (new_y[i] == buf_y[altbuf]) { + SWAPP (SI_BUF(si,1), SI_BUF(si,2)) + SWAPI (buf_y[1], buf_y[2]) + + } else { + # Get line and interpolate onto output grid. If interpolation + # is not required merely copy data out. This code is set up + # to always use two buffers; in effect, there is one buffer of + # look ahead, even when Y[i] is integral. This means that we + # will go out of bounds by one line at the top of the image. + # This is handled by copying the last line. + + ybavg = SI_BAVG(si,2) + nblks_y = (IM_LEN (SI_IM(si), 2) + ybavg-1) / ybavg + if (new_y[i] <= nblks_y) + rawline = si_blkavgr (SI_IM(si), x1, x2, new_y[i], + SI_BAVG(si,1), SI_BAVG(si,2)) + + if (SI_INTERP(si,1) == NO) + call amovr (Memr[rawline], Memr[SI_BUF(si,i)], npix) + else { + call aluir (Memr[rawline], Memr[SI_BUF(si,i)], + Memr[SI_GRID(si,1)], npix) + } + + buf_y[i] = new_y[i] + } + + SWAPI (altbuf, curbuf) + } + + # We now have two line buffers straddling the output Y value, + # interpolated to the X grid of the output line. To complete the + # bilinear interpolation operation we take a weighted sum of the two + # lines. If the range from buf_y[1] to buf_y[2] is repeatedly + # interpolated in Y no additional i/o occurs and the linear + # interpolation operation (ALUI) does not have to be repeated (only the + # weighted sum is required). If the distance of Y from one of the + # buffers is zero then we do not even have to take a weighted sum. + # This is not unusual because we may be called with a magnification + # of 1.0 in Y. + + weight_1 = 1.0 - (y - buf_y[1]) + weight_2 = 1.0 - weight_1 + + if (weight_2 < SI_TOL) + return (SI_BUF(si,1)) + else if (weight_1 < SI_TOL) + return (SI_BUF(si,2)) + else { + call awsur (Memr[SI_BUF(si,1)], Memr[SI_BUF(si,2)], + Memr[OUTBUF(si)], npix, weight_1, weight_2) + return (OUTBUF(si)) + } +end + + +# SI_BLKAVGR -- Get a line from a block averaged image of type short. +# For example, block averaging by a factor of 2 means that pixels 1 and 2 +# are averaged to produce the first output pixel, 3 and 4 are averaged to +# produce the second output pixel, and so on. If the length of an axis +# is not an integral multiple of the block size then the last pixel in the +# last block will be replicated to fill out the block; the average is still +# defined even if a block is not full. + +pointer procedure si_blkavgr (im, x1, x2, y, xbavg, ybavg) + +pointer im # input image +int x1, x2 # range of x blocks to be read +int y # y block to be read +int xbavg, ybavg # X and Y block averaging factors + +int nblks_x, nblks_y, ncols, nlines, xoff, i, j +int first_line, nlines_in_sum, npix, nfull_blks, count +real sum +pointer sp, a, b +pointer imgs2r() +errchk imgs2r + +begin + call smark (sp) + + ncols = IM_LEN(im,1) + nlines = IM_LEN(im,2) + xoff = (x1 - 1) * xbavg + 1 + npix = min (ncols, xoff + (x2 - x1 + 1) * xbavg - 1) + + if ((xbavg < 1) || (ybavg < 1)) + call error (1, "si_blkavg: illegal block size") + else if (x1 < 1 || x2 > ncols) + call error (2, "si_blkavg: column index out of bounds") + else if ((xbavg == 1) && (ybavg == 1)) + return (imgs2r (im, xoff, xoff + npix - 1, y, y)) + + nblks_x = (npix + xbavg-1) / xbavg + nblks_y = (nlines + ybavg-1) / ybavg + + if (y < 1 || y > nblks_y) + call error (2, "si_blkavg: block number out of range") + + call salloc (b, nblks_x, TY_REAL) + + if (ybavg > 1) { + call aclrr (Memr[b], nblks_x) + nlines_in_sum = 0 + } + + # Read and accumulate all input lines in the block. + first_line = (y - 1) * ybavg + 1 + + do i = first_line, min (nlines, first_line + ybavg - 1) { + # Get line from input image. + a = imgs2r (im, xoff, xoff + npix - 1, i, i) + + # Block average line in X. + if (xbavg > 1) { + # First block average only the full blocks. + nfull_blks = npix / xbavg + call abavr (Memr[a], Memr[a], nfull_blks, xbavg) + + # Now average the final partial block, if any. + if (nfull_blks < nblks_x) { + sum = 0.0 + count = 0 + do j = nfull_blks * xbavg + 1, npix { + sum = sum + Memr[a+j-1] + count = count + 1 + } + Memr[a+nblks_x-1] = sum / count + } + } + + # Add line into block sum. Keep track of number of lines in sum + # so that we can compute block average later. + if (ybavg > 1) { + call aaddr (Memr[a], Memr[b], Memr[b], nblks_x) + nlines_in_sum = nlines_in_sum + 1 + } + } + + # Compute the block average in Y from the sum of all lines block + # averaged in X. Overwrite buffer A, the buffer returned by IMIO. + # This is kosher because the block averaged line is never longer + # than an input line. + + if (ybavg > 1) + call adivkr (Memr[b], real(nlines_in_sum), Memr[a], nblks_x) + + call sfree (sp) + return (a) +end diff --git a/pkg/images/tv/iis/src/snap.x b/pkg/images/tv/iis/src/snap.x new file mode 100644 index 00000000..12694568 --- /dev/null +++ b/pkg/images/tv/iis/src/snap.x @@ -0,0 +1,64 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include <imhdr.h> +include <gki.h> +include "../lib/ids.h" + +# SNAP -- Take a picture!! + +procedure snap() + +char token[SZ_LINE] +int tok +char fname[SZ_FNAME] +int snap_color + +include "cv.com" + +begin + snap_color = IDS_SNAP_MONO # default color for snap + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (tok == TOK_IDENTIFIER) { + if (token[1] != 'c') { + call eprintf ("unknown snap argument: %s\n") + call pargstr (token) + return + } else { + # snap colors: r, g, b, rgb, m (monochrome) == bw (black/white) + switch (token[2]) { + case 'm': + snap_color = IDS_SNAP_MONO + + case 'r': + if ((token[3] == 'g') && (token[4] == 'b') ) + snap_color = IDS_SNAP_RGB + else + snap_color = IDS_SNAP_RED + + case 'g': + snap_color = IDS_SNAP_GREEN + + case 'b': + if (token[3] == 'w') + snap_color = IDS_SNAP_MONO + else + snap_color = IDS_SNAP_BLUE + + default: + call eprintf ("Unknown snap color: %c\n") + call pargc (token[2]) + return + } + } + } else if (tok != TOK_NEWLINE) { + call eprintf ("unexpected argument to snap: %s\n") + call pargstr (token) + return + } + + call clgstr("snap_file", fname, SZ_FNAME) + call cvsnap (fname, snap_color) +end diff --git a/pkg/images/tv/iis/src/split.x b/pkg/images/tv/iis/src/split.x new file mode 100644 index 00000000..393fc218 --- /dev/null +++ b/pkg/images/tv/iis/src/split.x @@ -0,0 +1,95 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include "../lib/ids.h" + +# SPLIT -- set the split screen point + +procedure split() + +char token[SZ_LINE] +int tok +int nchar, ctoi() +int i, x, y +real xr, yr +int ctor() +bool a_real + +define errmsg 10 + +include "cv.com" + +begin + a_real = false + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (tok == TOK_IDENTIFIER) { + switch(token[1]) { + case 'c': + x = cv_xcen + y = cv_ycen + + case 'o': + x = 1 + y = 1 + + case 'n', 'p': # n: ndc, p: pixel + if (token[1] == 'n') + a_real = true + if (IS_DIGIT(token[2])) + i = 2 + else { + call gargtok (tok, token, SZ_LINE) + if (tok != TOK_NUMBER) { +errmsg + call eprintf ("bad split pixel: %s\n") + call pargstr (token) + return + } else + i = 1 + } + if (a_real) + nchar = ctor (token, i, xr) + else + nchar = ctoi (token, i, x) + if (nchar == 0) { + call eprintf ("No conversion, ") + goto errmsg + } + call gargtok (tok, token, SZ_LINE) + if (tok == TOK_PUNCTUATION) + call gargtok (tok, token, SZ_LINE) + i = 1 + if (a_real) + nchar = ctor (token, i, yr) + else + nchar = ctoi (token, i, y) + if (nchar == 0) { + call eprintf ("No conversion, ") + goto errmsg + } + + default: + call eprintf ("unknown split code: %c\n") + call pargc (token[1]) + return + } + } + # Convert to NDC, BUT note, that as x and y range from 1 through + # cv_[xy]res, xr and yr will never be 1.0---and they must not be + # (see cvsplit()) + if (!a_real ) { + xr = real(x-1) / cv_xres + yr = real(y-1) / cv_xres + } + if ( xr < 0 ) + xr = 0 + if ( yr < 0 ) + yr = 0 + if ( xr >= 1.0 ) + xr = real(cv_xres-1)/cv_xres + if ( yr >= 1.0 ) + yr = real(cv_yres-1)/cv_yres + call cvsplit (xr, yr) +end diff --git a/pkg/images/tv/iis/src/tell.x b/pkg/images/tv/iis/src/tell.x new file mode 100644 index 00000000..cce4987e --- /dev/null +++ b/pkg/images/tv/iis/src/tell.x @@ -0,0 +1,24 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + + +include "../lib/ids.h" + +# TELL -- Tell user about display state + +procedure tell() + +short f[IDS_MAXIMPL+2] # Ultimately, want an array terminated + # with IDS_EOD as usual + +include "cv.com" + +begin + # We don't know much, do we? + + call cvwhich(f) + if ( f[1] > 0) { + call eprintf ("Frame %d, at least, is on.\n") + call pargs (f[1]) + } else + call eprintf ("No frames are on.\n") +end diff --git a/pkg/images/tv/iis/src/text.x b/pkg/images/tv/iis/src/text.x new file mode 100644 index 00000000..32623786 --- /dev/null +++ b/pkg/images/tv/iis/src/text.x @@ -0,0 +1,71 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include "../lib/ids.h" + +# TEXT -- put text into image planes or graphics bit planes + +procedure text() + +char token[SZ_LINE] +int tok, ip, cnum +short frames[IDS_MAXIMPL+2] # frames, graphics, EOD +short colors[IDS_MAXGCOLOR] +real x, y +int button, cv_wtbut() +char line[SZ_LINE] +real size, clgetr() + +begin + frames[1] = ERR + colors[1] = ERR + + # which frames for text + + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (tok == TOK_IDENTIFIER) { + if (token[1] == 'f') { + call cv_frame (token[2], frames) + if (frames[1] == ERR) + return + } else if (token[1] == 'c') { + call cv_color (token[2], colors) + if (colors[1] == ERR) + return + } + } else if (tok == TOK_NUMBER) { + call cv_frame (token[1], frames) + if (frames[1] == ERR) + return + } + if ( (frames[1] == ERR) && (colors[1] == ERR)) { + call eprintf ("Inadequate text specification: %s\n") + call pargstr (token) + return + } + + call gargstr (line, SZ_LINE) + + # Prompt user to set cursor + + call eprintf ("Set cursor to desired location, then press any button\n") + button = cv_wtbut() + + # Set up kernel for write + if (frames[1] != ERR) { + cnum = frames[1] + call cv_iset (frames) + } else { + cnum = 16 # SORRY, is IIS specific - we should do better + call cv_gset (colors) + } + call cv_rcur (cnum, x, y) + + size = clgetr("textsize") + ip = 1 + while (IS_WHITE(line[ip])) + ip = ip + 1 + call cvtext (x, y, line[ip], size) +end diff --git a/pkg/images/tv/iis/src/window.x b/pkg/images/tv/iis/src/window.x new file mode 100644 index 00000000..e3523a90 --- /dev/null +++ b/pkg/images/tv/iis/src/window.x @@ -0,0 +1,181 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include <gki.h> +include "../lib/ids.h" + +# WINDOW -- window the display. + +procedure window() + +char token[SZ_LINE] +int tok, cnum +short frames[IDS_MAXIMPL+2] # frames, graphics, EOD +short colors[IDS_MAXGCOLOR] +real x, y +real xold, yold +int device, button, cv_rdbut() +short wdata[16] +int n, first, last +real istart, iend, slope + +include "cv.com" + +begin + # Find out if want to change output tables + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (( tok == TOK_IDENTIFIER) && (token[1] == 'o')) { + device = IDS_OUTPUT_LUT + slope = 4.0 # Device dependent !! + } else { + device = IDS_FRAME_LUT + slope = 1.0 + # reset input pointers; same as having pushed back token + call reset_scan + call gargtok (tok, token, SZ_LINE) + } + + # Default to all frames, all colors + frames[1] = IDS_EOD + colors[1] = IDS_EOD + + # which frames to window + + repeat { + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (tok == TOK_IDENTIFIER) { + if (token[1] == 'f') { + call cv_frame (token[2], frames) + if (frames[1] == ERR) + return + } else if (token[1] == 'c') { + call cv_color (token[2], colors) + if (colors[1] == ERR) + return + } else { + call eprintf ("Unknown window argument: %s\n") + call pargstr (token) + return + } + } else if (tok == TOK_NUMBER) { + call cv_frame (token[1], frames) + if (frames[1] == ERR) + return + } else if (tok != TOK_NEWLINE) { + call eprintf ("Unexpected window input: %s\n") + call pargstr (token) + return + } + } until ( tok == TOK_NEWLINE) + + # rememeber current cursor postion + + cnum = 0 + call cv_rcur (cnum, xold, yold) + + # Now set up loop to window display; we need to read back + # display but cannot, so for now, use "common" variables + # If first time, use defaults. + + if (cv_xwinc == -1) { + if (slope == 1.0) { + cv_xwinc = 0.25 + cv_ywinc = .75 + } else { + cv_xwinc = .0625 + cv_ywinc = .9375 + } + } + call cv_scraw (cv_xwinc, cv_ywinc) + + button = cv_rdbut() # clear buttons by reading them + call eprintf ("Press any button when done\n") + + # The mapping equation is table value = 0.25 + y * (i-x) + # where i runs from 0 to 1.0, x ranges from 0. to 1.0 and y + # from 0 to large. + + repeat { + call cv_rcraw (cv_xwinc, cv_ywinc) + x = cv_xwinc + y = (cv_ywinc - 0.5) * 4 + # Keep y from equalling 2 or -2 : + if (y >= 2.) + y = 1.99 + else if ( y <= -2.0) + y = -1.99 + if (y > 1.) + y = 1. / (2. - y) + else if (y < -1.) + y = -1. / (2. + y) + + if ( y == 0.0) { + iend = 1.0 + istart = 0.0 + first = 0 + last = GKI_MAXNDC + } else if ( y > 0.) { + istart = x - 0.25/y + iend = 1.0/y + istart + first = 0 + last = GKI_MAXNDC + } else { + iend = x - 0.25/y + istart = 1.0/y + iend + first = GKI_MAXNDC + last = 0 + } + if (istart < 0.) + istart = 0. + if (iend > 1.0) + iend = 1.0 + if (istart > 1.0) + istart = 1.0 + if (iend < istart) + iend = istart + wdata[1] = 0 + if ( istart > 0.) { + wdata[2] = first + wdata[3] = istart * GKI_MAXNDC + wdata[4] = first + n = 5 + } else { + wdata[2] = (0.25 -x*y) * GKI_MAXNDC + n = 3 + } + wdata[n] = iend * GKI_MAXNDC + if ( iend < 1.0) { + # In this case, we reach max/min y value before end of table, so + # extend it horizontally to end + wdata[n+1] = last + wdata[n+2] = GKI_MAXNDC + wdata[n+3] = last + n = n + 3 + } else { + wdata[n+1] = (0.25 + y * (1.0 - x)) * GKI_MAXNDC + n = n + 1 + } + call cvwlut (device, frames, colors, wdata, n) + button = cv_rdbut() + } until (button > 0) + + # Restore old cursor position + call cv_rcur (cnum, xold, yold) + + # Tell the user what final mapping was + call printf ("window: from (%5.3f,%5.3f) to (%5.3f,%5.3f)\n") + call pargr (istart) + if (istart > 0.) + call pargr (real(first)/GKI_MAXNDC) + else + call pargr (real(wdata[2])/GKI_MAXNDC) + call pargr (iend) + if (iend < 1.0) + call pargr (real(last)/GKI_MAXNDC) + else + call pargr (real(wdata[n])/GKI_MAXNDC) + +end diff --git a/pkg/images/tv/iis/src/zoom.x b/pkg/images/tv/iis/src/zoom.x new file mode 100644 index 00000000..c7e7bff7 --- /dev/null +++ b/pkg/images/tv/iis/src/zoom.x @@ -0,0 +1,60 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctotok.h> +include <ctype.h> +include <gki.h> +include "../lib/ids.h" + +# ZOOM -- zoom, then pan, the display. If zoom power == 1, then +# don't bother panning. + +procedure zoom() + +char token[SZ_LINE] +int tok, count, power, cnum +short frames[IDS_MAXIMPL+2] # frames, graphics, EOD +real x, y +int ctoi, ip + +include "cv.com" + +begin + # get power for zoom + + call gargtok (tok, token, SZ_LINE) + if (tok != TOK_NUMBER) { + call eprintf ("Bad zoom power: %s\n") + call pargstr (token) + return + } + ip = 1 + count = ctoi(token, ip, power) + + # which frames to zoom + + frames[1] = IDS_EOD # default all frames + call gargtok (tok, token, SZ_LINE) + call strlwr (token) + if (token[1] == 'f') { + call cv_frame (token[2], frames) + if (frames[1] == ERR) + return + } else if (tok == TOK_NUMBER) { + call cv_frame (token[1], frames) + if (frames[1] == ERR) + return + } else { + call eprintf ("Unexpected input: %s\n") + call pargstr (token) + return + } + + # where to zoom ... find which frame to read cursor position from + + cnum = frames[1] + if (cnum == IDS_EOD) + cnum = 0 + call cv_rcur (cnum, x, y) + call cvzoom (frames, power, x, y) + call pansub (frames) +end diff --git a/pkg/images/tv/iis/src/zscale.x b/pkg/images/tv/iis/src/zscale.x new file mode 100644 index 00000000..bfb0b116 --- /dev/null +++ b/pkg/images/tv/iis/src/zscale.x @@ -0,0 +1,457 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <imhdr.h> + +.help zscale +.nf ___________________________________________________________________________ +ZSCALE -- Compute the optimal Z1, Z2 (range of greyscale values to be +displayed) of an image. For efficiency a statistical subsample of an image +is used. The pixel sample evenly subsamples the image in x and y. The entire +image is used if the number of pixels in the image is smaller than the desired +sample. + +The sample is accumulated in a buffer and sorted by greyscale value. +The median value is the central value of the sorted array. The slope of a +straight line fitted to the sorted sample is a measure of the standard +deviation of the sample about the median value. Our algorithm is to sort +the sample and perform an iterative fit of a straight line to the sample, +using pixel rejection to omit gross deviants near the endpoints. The fitted +straight line is the transfer function used to map image Z into display Z. +If more than half the pixels are rejected the full range is used. The slope +of the fitted line is divided by the user-supplied contrast factor and the +final Z1 and Z2 are computed, taking the origin of the fitted line at the +median value. +.endhelp ______________________________________________________________________ + +define MIN_NPIXELS 5 # smallest permissible sample +define MAX_REJECT 0.5 # max frac. of pixels to be rejected +define GOOD_PIXEL 0 # use pixel in fit +define BAD_PIXEL 1 # ignore pixel in all computations +define REJECT_PIXEL 2 # reject pixel after a bit +define KREJ 2.5 # k-sigma pixel rejection factor +define MAX_ITERATIONS 5 # maximum number of fitline iterations + + +# ZSCALE -- Sample the image and compute Z1 and Z2. + +procedure zscale (im, z1, z2, contrast, optimal_sample_size, len_stdline) + +pointer im # image to be sampled +real z1, z2 # output min and max greyscale values +real contrast # adj. to slope of transfer function +int optimal_sample_size # desired number of pixels in sample +int len_stdline # optimal number of pixels per line + +int npix, minpix, ngoodpix, center_pixel, ngrow +real zmin, zmax, median +real zstart, zslope +pointer sample, left +int zsc_sample_image(), zsc_fit_line() + +begin + # Subsample the image. + npix = zsc_sample_image (im, sample, optimal_sample_size, len_stdline) + center_pixel = max (1, (npix + 1) / 2) + + # Sort the sample, compute the minimum, maximum, and median pixel + # values. + + call asrtr (Memr[sample], Memr[sample], npix) + zmin = Memr[sample] + zmax = Memr[sample+npix-1] + + # The median value is the average of the two central values if there + # are an even number of pixels in the sample. + + left = sample + center_pixel - 1 + if (mod (npix, 2) == 1 || center_pixel >= npix) + median = Memr[left] + else + median = (Memr[left] + Memr[left+1]) / 2 + + # Fit a line to the sorted sample vector. If more than half of the + # pixels in the sample are rejected give up and return the full range. + # If the user-supplied contrast factor is not 1.0 adjust the scale + # accordingly and compute Z1 and Z2, the y intercepts at indices 1 and + # npix. + + minpix = max (MIN_NPIXELS, int (npix * MAX_REJECT)) + ngrow = max (1, nint (npix * .01)) + ngoodpix = zsc_fit_line (Memr[sample], npix, zstart, zslope, + KREJ, ngrow, MAX_ITERATIONS) + + if (ngoodpix < minpix) { + z1 = zmin + z2 = zmax + } else { + if (contrast > 0) + zslope = zslope / contrast + z1 = max (zmin, median - (center_pixel - 1) * zslope) + z2 = min (zmax, median + (npix - center_pixel) * zslope) + } + + call mfree (sample, TY_REAL) +end + + +# ZSC_SAMPLE_IMAGE -- Extract an evenly gridded subsample of the pixels from +# a two-dimensional image into a one-dimensional vector. + +int procedure zsc_sample_image (im, sample, optimal_sample_size, len_stdline) + +pointer im # image to be sampled +pointer sample # output vector containing the sample +int optimal_sample_size # desired number of pixels in sample +int len_stdline # optimal number of pixels per line + +int ncols, nlines, col_step, line_step, maxpix, line +int opt_npix_per_line, npix_per_line +int opt_nlines_in_sample, min_nlines_in_sample, max_nlines_in_sample +pointer op +pointer imgl2r() + +begin + ncols = IM_LEN(im,1) + nlines = IM_LEN(im,2) + + # Compute the number of pixels each line will contribute to the sample, + # and the subsampling step size for a line. The sampling grid must + # span the whole line on a uniform grid. + + opt_npix_per_line = min (ncols, len_stdline) + col_step = (ncols + opt_npix_per_line-1) / opt_npix_per_line + npix_per_line = (ncols + col_step-1) / col_step + + # Compute the number of lines to sample and the spacing between lines. + # We must ensure that the image is adequately sampled despite its + # size, hence there is a lower limit on the number of lines in the + # sample. We also want to minimize the number of lines accessed when + # accessing a large image, because each disk seek and read is expensive. + # The number of lines extracted will be roughly the sample size divided + # by len_stdline, possibly more if the lines are very short. + + min_nlines_in_sample = max (1, optimal_sample_size / len_stdline) + opt_nlines_in_sample = max(min_nlines_in_sample, min(nlines, + (optimal_sample_size + npix_per_line-1) / npix_per_line)) + line_step = max (1, nlines / (opt_nlines_in_sample)) + max_nlines_in_sample = (nlines + line_step-1) / line_step + + # Allocate space for the output vector. Buffer must be freed by our + # caller. + + maxpix = npix_per_line * max_nlines_in_sample + call malloc (sample, maxpix, TY_REAL) + +# call eprintf ("sample: x[%d:%d:%d] y[%d:%d:%d]\n") +# call pargi(1);call pargi(ncols); call pargi(col_step) +# call pargi((line_step+1)/2); call pargi(nlines); call pargi(line_step) + + # Extract the vector. + op = sample + do line = (line_step + 1) / 2, nlines, line_step { + call zsc_subsample (Memr[imgl2r(im,line)], Memr[op], + npix_per_line, col_step) + op = op + npix_per_line + if (op - sample + npix_per_line > maxpix) + break + } + + return (op - sample) +end + + +# ZSC_SUBSAMPLE -- Subsample an image line. Extract the first pixel and +# every "step"th pixel thereafter for a total of npix pixels. + +procedure zsc_subsample (a, b, npix, step) + +real a[ARB] +real b[npix] +int npix, step +int ip, i + +begin + if (step <= 1) + call amovr (a, b, npix) + else { + ip = 1 + do i = 1, npix { + b[i] = a[ip] + ip = ip + step + } + } +end + + +# ZSC_FIT_LINE -- Fit a straight line to a data array of type real. This is +# an iterative fitting algorithm, wherein points further than ksigma from the +# current fit are excluded from the next fit. Convergence occurs when the +# next iteration does not decrease the number of pixels in the fit, or when +# there are no pixels left. The number of pixels left after pixel rejection +# is returned as the function value. + +int procedure zsc_fit_line (data, npix, zstart, zslope, krej, ngrow, maxiter) + +real data[npix] # data to be fitted +int npix # number of pixels before rejection +real zstart # Z-value of pixel data[1] (output) +real zslope # dz/pixel (output) +real krej # k-sigma pixel rejection factor +int ngrow # number of pixels of growing +int maxiter # max iterations + +int i, ngoodpix, last_ngoodpix, minpix, niter +real xscale, z0, dz, x, z, mean, sigma, threshold +double sumxsqr, sumxz, sumz, sumx, rowrat +pointer sp, flat, badpix, normx +int zsc_reject_pixels(), zsc_compute_sigma() + +begin + call smark (sp) + + if (npix <= 0) + return (0) + else if (npix == 1) { + zstart = data[1] + zslope = 0.0 + return (1) + } else + xscale = 2.0 / (npix - 1) + + # Allocate a buffer for data minus fitted curve, another for the + # normalized X values, and another to flag rejected pixels. + + call salloc (flat, npix, TY_REAL) + call salloc (normx, npix, TY_REAL) + call salloc (badpix, npix, TY_SHORT) + call aclrs (Mems[badpix], npix) + + # Compute normalized X vector. The data X values [1:npix] are + # normalized to the range [-1:1]. This diagonalizes the lsq matrix + # and reduces its condition number. + + do i = 0, npix - 1 + Memr[normx+i] = i * xscale - 1.0 + + # Fit a line with no pixel rejection. Accumulate the elements of the + # matrix and data vector. The matrix M is diagonal with + # M[1,1] = sum x**2 and M[2,2] = ngoodpix. The data vector is + # DV[1] = sum (data[i] * x[i]) and DV[2] = sum (data[i]). + + sumxsqr = 0 + sumxz = 0 + sumx = 0 + sumz = 0 + + do i = 1, npix { + x = Memr[normx+i-1] + z = data[i] + sumxsqr = sumxsqr + (x ** 2) + sumxz = sumxz + z * x + sumz = sumz + z + } +# call eprintf ("\t%10g %10g %10g\n") +# call pargd(sumxsqr); call pargd(sumxz); call pargd(sumz) + + # Solve for the coefficients of the fitted line. + z0 = sumz / npix + dz = sumxz / sumxsqr + +# call eprintf ("fit: z0=%g, dz=%g\n") +# call pargr(z0); call pargr(dz) + + # Iterate, fitting a new line in each iteration. Compute the flattened + # data vector and the sigma of the flat vector. Compute the lower and + # upper k-sigma pixel rejection thresholds. Run down the flat array + # and detect pixels to be rejected from the fit. Reject pixels from + # the fit by subtracting their contributions from the matrix sums and + # marking the pixel as rejected. + + ngoodpix = npix + minpix = max (MIN_NPIXELS, int (npix * MAX_REJECT)) + + for (niter=1; niter <= maxiter; niter=niter+1) { + last_ngoodpix = ngoodpix + + # Subtract the fitted line from the data array. + call zsc_flatten_data (data, Memr[flat], Memr[normx], npix, z0, dz) + + # Compute the k-sigma rejection threshold. In principle this + # could be more efficiently computed using the matrix sums + # accumulated when the line was fitted, but there are problems with + # numerical stability with that approach. + + ngoodpix = zsc_compute_sigma (Memr[flat], Mems[badpix], npix, + mean, sigma) + threshold = sigma * krej + + # Detect and reject pixels further than ksigma from the fitted + # line. + ngoodpix = zsc_reject_pixels (data, Memr[flat], Memr[normx], + Mems[badpix], npix, sumxsqr, sumxz, sumx, sumz, threshold, + ngrow) + + # Solve for the coefficients of the fitted line. Note that after + # pixel rejection the sum of the X values need no longer be zero. + + if (ngoodpix > 0) { + rowrat = sumx / sumxsqr + z0 = (sumz - rowrat * sumxz) / (ngoodpix - rowrat * sumx) + dz = (sumxz - z0 * sumx) / sumxsqr + } + +# call eprintf ("fit: z0=%g, dz=%g, threshold=%g, npix=%d\n") +# call pargr(z0); call pargr(dz); call pargr(threshold); call pargi(ngoodpix) + + if (ngoodpix >= last_ngoodpix || ngoodpix < minpix) + break + } + + # Transform the line coefficients back to the X range [1:npix]. + zstart = z0 - dz + zslope = dz * xscale + + call sfree (sp) + return (ngoodpix) +end + + +# ZSC_FLATTEN_DATA -- Compute and subtract the fitted line from the data array, +# returned the flattened data in FLAT. + +procedure zsc_flatten_data (data, flat, x, npix, z0, dz) + +real data[npix] # raw data array +real flat[npix] # flattened data (output) +real x[npix] # x value of each pixel +int npix # number of pixels +real z0, dz # z-intercept, dz/dx of fitted line +int i + +begin + do i = 1, npix + flat[i] = data[i] - (x[i] * dz + z0) +end + + +# ZSC_COMPUTE_SIGMA -- Compute the root mean square deviation from the +# mean of a flattened array. Ignore rejected pixels. + +int procedure zsc_compute_sigma (a, badpix, npix, mean, sigma) + +real a[npix] # flattened data array +short badpix[npix] # bad pixel flags (!= 0 if bad pixel) +int npix +real mean, sigma # (output) + +real pixval +int i, ngoodpix +double sum, sumsq, temp + +begin + sum = 0 + sumsq = 0 + ngoodpix = 0 + + # Accumulate sum and sum of squares. + do i = 1, npix + if (badpix[i] == GOOD_PIXEL) { + pixval = a[i] + ngoodpix = ngoodpix + 1 + sum = sum + pixval + sumsq = sumsq + pixval ** 2 + } + + # Compute mean and sigma. + switch (ngoodpix) { + case 0: + mean = INDEF + sigma = INDEF + case 1: + mean = sum + sigma = INDEF + default: + mean = sum / ngoodpix + temp = sumsq / (ngoodpix - 1) - sum**2 / (ngoodpix * (ngoodpix - 1)) + if (temp < 0) # possible with roundoff error + sigma = 0.0 + else + sigma = sqrt (temp) + } + + return (ngoodpix) +end + + +# ZSC_REJECT_PIXELS -- Detect and reject pixels more than "threshold" greyscale +# units from the fitted line. The residuals about the fitted line are given +# by the "flat" array, while the raw data is in "data". Each time a pixel +# is rejected subtract its contributions from the matrix sums and flag the +# pixel as rejected. When a pixel is rejected reject its neighbors out to +# a specified radius as well. This speeds up convergence considerably and +# produces a more stringent rejection criteria which takes advantage of the +# fact that bad pixels tend to be clumped. The number of pixels left in the +# fit is returned as the function value. + +int procedure zsc_reject_pixels (data, flat, normx, badpix, npix, + sumxsqr, sumxz, sumx, sumz, threshold, ngrow) + +real data[npix] # raw data array +real flat[npix] # flattened data array +real normx[npix] # normalized x values of pixels +short badpix[npix] # bad pixel flags (!= 0 if bad pixel) +int npix +double sumxsqr,sumxz,sumx,sumz # matrix sums +real threshold # threshold for pixel rejection +int ngrow # number of pixels of growing + +int ngoodpix, i, j +real residual, lcut, hcut +double x, z + +begin + ngoodpix = npix + lcut = -threshold + hcut = threshold + + do i = 1, npix + if (badpix[i] == BAD_PIXEL) + ngoodpix = ngoodpix - 1 + else { + residual = flat[i] + if (residual < lcut || residual > hcut) { + # Reject the pixel and its neighbors out to the growing + # radius. We must be careful how we do this to avoid + # directional effects. Do not turn off thresholding on + # pixels in the forward direction; mark them for rejection + # but do not reject until they have been thresholded. + # If this is not done growing will not be symmetric. + + do j = max(1,i-ngrow), min(npix,i+ngrow) { +#call eprintf ("\t\t%d->%d\tcheck\n");call pargi(j); call pargs(badpix[j]) + if (badpix[j] != BAD_PIXEL) { + if (j <= i) { + x = normx[j] + z = data[j] +#call eprintf ("\treject [%d:%6g]=%6g sum[xsqr,xz,z]\n") +#call pargi(j); call pargd(x); call pargd(z) +#call eprintf ("\t%10g %10g %10g\n") +#call pargd(sumxsqr); call pargd(sumxz); call pargd(sumz) + sumxsqr = sumxsqr - (x ** 2) + sumxz = sumxz - z * x + sumx = sumx - x + sumz = sumz - z +#call eprintf ("\t%10g %10g %10g\n") +#call pargd(sumxsqr); call pargd(sumxz); call pargd(sumz) + badpix[j] = BAD_PIXEL + ngoodpix = ngoodpix - 1 + } else + badpix[j] = REJECT_PIXEL +#call eprintf ("\t\t%d->%d\tset\n");call pargi(j); call pargs(badpix[j]) + } + } + } + } + + return (ngoodpix) +end |