aboutsummaryrefslogtreecommitdiff
path: root/pkg/dataio/import
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /pkg/dataio/import
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/dataio/import')
-rw-r--r--pkg/dataio/import/README2
-rw-r--r--pkg/dataio/import/bltins/README13
-rw-r--r--pkg/dataio/import/bltins/ipcmap.x76
-rw-r--r--pkg/dataio/import/bltins/ipgif.x883
-rw-r--r--pkg/dataio/import/bltins/ipras.x504
-rw-r--r--pkg/dataio/import/bltins/ipxwd.x188
-rw-r--r--pkg/dataio/import/bltins/mkpkg13
-rw-r--r--pkg/dataio/import/fmtdb.x610
-rw-r--r--pkg/dataio/import/generic/ipdb.x813
-rw-r--r--pkg/dataio/import/generic/ipfio.x569
-rw-r--r--pkg/dataio/import/generic/ipobands.x375
-rw-r--r--pkg/dataio/import/generic/ipproc.x921
-rw-r--r--pkg/dataio/import/generic/mkpkg15
-rw-r--r--pkg/dataio/import/images.dat433
-rw-r--r--pkg/dataio/import/import.h132
-rw-r--r--pkg/dataio/import/ipbuiltin.x91
-rw-r--r--pkg/dataio/import/ipdb.gx766
-rw-r--r--pkg/dataio/import/ipfcn.h57
-rw-r--r--pkg/dataio/import/ipfio.gx443
-rw-r--r--pkg/dataio/import/ipinfo.x256
-rw-r--r--pkg/dataio/import/iplistpix.x137
-rw-r--r--pkg/dataio/import/ipmkhdr.x63
-rw-r--r--pkg/dataio/import/ipobands.gx306
-rw-r--r--pkg/dataio/import/ipproc.gx804
-rw-r--r--pkg/dataio/import/mkpkg37
-rw-r--r--pkg/dataio/import/t_import.x768
-rw-r--r--pkg/dataio/import/zzidbg.x145
27 files changed, 9420 insertions, 0 deletions
diff --git a/pkg/dataio/import/README b/pkg/dataio/import/README
new file mode 100644
index 00000000..20ab02a1
--- /dev/null
+++ b/pkg/dataio/import/README
@@ -0,0 +1,2 @@
+This directory contains the source code for the IMPORT <something>-to-IRAF
+format conversion task.
diff --git a/pkg/dataio/import/bltins/README b/pkg/dataio/import/bltins/README
new file mode 100644
index 00000000..c15b9cfe
--- /dev/null
+++ b/pkg/dataio/import/bltins/README
@@ -0,0 +1,13 @@
+ This directory contains the source code for the 'builtin' formats
+converted with IMPORT. Here we implement three formats that require different
+levels of processing: the GIF format uses LZW compression and a colormap for
+pixel storage and requires the most work, Sun Rasterfiles have various formats
+that may require colormap application or RLE decoding, and lastly the X
+Window Dump format that fits the generic binary raster model with the exception
+of an 8-bit file with a colormap.
+ Because formats are defined in the data base the user is unaware of
+any special processing that occurs unless implementing a new format that
+requires partivular handling. In the case of colormap files the example of
+XWD can be followed and all that's needed is a routine to read the colormap
+from the image. 'Builtin' formats must, however, be declared in the source
+import$ipbuiltin.x to route execution to the format-specific code.
diff --git a/pkg/dataio/import/bltins/ipcmap.x b/pkg/dataio/import/bltins/ipcmap.x
new file mode 100644
index 00000000..ad44a7cf
--- /dev/null
+++ b/pkg/dataio/import/bltins/ipcmap.x
@@ -0,0 +1,76 @@
+include "../import.h"
+
+# IPCMAP.X -- Procedures for colormap application or lookup.
+
+
+# IP_GRAY_CMAP - Apply the colormap to an array of pixels and convert the
+# pixels to grayscale using the NTSC formula.
+
+procedure ip_gray_cmap (data, len, cmap)
+
+char data[ARB] #i pixel values
+int len #i how many of 'em
+pointer cmap #i colormap pointer
+
+int i
+short val, ip_gcmap_val()
+
+begin
+ do i = 1, len {
+ val = data[i] + 1
+ data[i] = ip_gcmap_val (val, cmap)
+ }
+end
+
+
+# IP_GCMAP_VAL - Apply the colormap to a single pixel and convert the
+# result to grayscale using the NTSC formula.
+
+short procedure ip_gcmap_val (pix, cmap)
+
+char pix #i pixel value
+pointer cmap #i colormap pointer
+
+short val
+
+begin
+ val = (R_COEFF * CMAP(cmap,IP_RED,pix) +
+ G_COEFF * CMAP(cmap,IP_GREEN,pix) +
+ B_COEFF * CMAP(cmap,IP_BLUE,pix))
+ return (val)
+end
+
+
+# IP_RGB_VAL - Given a grayscale value figure out what the requested color
+# component is from the colormap.
+
+short procedure ip_rgb_val (pix, cmap, color)
+
+char pix #i pixel value
+pointer cmap #i colormap pointer
+int color #i requested color
+
+short i, val
+
+begin
+ # Need to optimize this later... For now just compute the colormap
+ # grayscale values until we find a match and use the index.
+ i = 0
+ val = -1
+ while (val != pix && i <= 256) {
+ i = i + 1
+ val = (R_COEFF * CMAP(cmap,IP_RED,i) +
+ G_COEFF * CMAP(cmap,IP_GREEN,i) +
+ B_COEFF * CMAP(cmap,IP_BLUE,i))
+ }
+
+ switch (color) {
+ case IP_RED:
+ val = CMAP(cmap,IP_RED,i-1)
+ case IP_GREEN:
+ val = CMAP(cmap,IP_GREEN,i-1)
+ case IP_BLUE:
+ val = CMAP(cmap,IP_BLUE,i-1)
+ }
+ return (val)
+end
diff --git a/pkg/dataio/import/bltins/ipgif.x b/pkg/dataio/import/bltins/ipgif.x
new file mode 100644
index 00000000..a7394e18
--- /dev/null
+++ b/pkg/dataio/import/bltins/ipgif.x
@@ -0,0 +1,883 @@
+include "../import.h"
+
+
+# IPGIF.X - Source file for the GIF builtin format converter.
+
+
+# Define the GIF data structure
+define MAX_CODE_ENTRIES 4096 # because LZW has 12 bit max
+define SZ_GIFSTRUCT 35
+define SZ_GIFCODE 280
+define SZ_GIFEXTN 256
+define SZ_GIFSTACK (2*MAX_CODE_ENTRIES+2)
+define SZ_GIFCTAB (2*MAX_CODE_ENTRIES+2)
+
+define GIF_FD Memi[$1] # GIF file descriptor
+define GIF_WIDTH Memi[$1+1] # Screen width
+define GIF_HEIGHT Memi[$1+2] # Screen height
+define GIF_CP Memi[$1+3] # Colormap pointer
+define GIF_BITPIX Memi[$1+4] # Bits per pixel
+define GIF_COLRES Memi[$1+5] # Color resolution
+define GIF_BACKGROUND Memi[$1+6] # background color (unused?)
+define GIF_ASPECT Memi[$1+7] # Aspect ratio
+define GIF_IMNUM Memi[$1+8] # Image number
+define GIF_CMAP Memi[$1+9] # Global colormap (ptr)
+
+define GIF_EXTBP Memi[$1+10] # Extension buffer (ptr)
+define GIF_CODEP Memi[$1+11] # Code table buffer (ptr)
+define GIF_CTABP Memi[$1+12] # Code table (ptr)
+define GIF_STACKP Memi[$1+13] # Stack (ptr)
+define GIF_CURBIT Memi[$1+14] # Decoder var
+define GIF_LASTBIT Memi[$1+15] # Decoder var
+define GIF_DONE Memi[$1+16] # Decoder var
+define GIF_LASTBYTE Memi[$1+17] # Decoder var
+define GIF_ZERO_DATABLOCK Memi[$1+18] # Decoder var
+define GIF_SP Memi[$1+19] # stack pointer
+
+define GIF_CLEAR_CODE Memi[$1+20] # LZW clear code
+define GIF_END_CODE Memi[$1+21] # LZW end code
+define GIF_FIRST_CODE Memi[$1+22] # LZW decoder var
+define GIF_OLD_CODE Memi[$1+23] # LZW decoder var
+define GIF_MAX_CODE Memi[$1+24] # LZW free code
+define GIF_MAX_CODE_SIZE Memi[$1+25] # LZW upper limit
+define GIF_CODE_SIZE Memi[$1+26] # LZW current code size
+define GIF_SET_CODE_SIZE Memi[$1+27] # LZW input code size
+define GIF_FRESH Memi[$1+28] # LZW init var
+
+# The following are used for GIF89a only.
+define GIF_TRANSPARENT Memi[$1+30] # Transparent Color Index
+define GIF_DELAYTIME Memi[$1+31] # Delay time
+define GIF_INPUTFLAG Memi[$1+32] # User input flag
+define GIF_DISPOSAL Memi[$1+33] # Disposal Method
+
+# Array macros.
+define CODEBUF Memc[GIF_CODEP($1)+$2]
+define EXTBUF Memc[GIF_EXTBP($1)+$2]
+define CODETAB Memc[GIF_CTABP($1)+($2*MAX_CODE_ENTRIES)+$3]
+define STACK Memc[GIF_STACKP($1)+$2]
+
+#---------------------------------------------------------------------------
+
+define INTERLACE 040X # Image descriptor flags
+define LOCAL_COLORMAP 080X
+
+# Define the flags for the GIF89a extension blocks.
+define GE_PLAINTEXT 001X # Plain Text Extension
+define GE_APPLICATION 0FFX # Application Extension
+define GE_COMMENT 0FEX # Comment Extension
+define GE_GCONTROL 0F9X # Graphics Control Extension
+
+define DEBUG false
+define VDEBUG false
+
+
+# IP_GIF - Read and process a GIF format file into an IRAF image.
+
+procedure ip_gif (ip, fname, info_only, verbose)
+
+pointer ip #i import struct pointer
+char fname[ARB] #i file name
+int info_only #i print out image info only?
+int verbose #i verbosity flag
+
+pointer gif
+int fd
+int bitpix, use_global_cmap, interlace
+int width, height, version
+char ch
+short sig[7], screen[12]
+
+pointer gif_open()
+int btoi(), strncmp(), gif_rdbyte(), gif_getbytes()
+int shifti()
+
+long filepos
+common /gifcom/ filepos
+
+begin
+ # Allocate the gif struct pointer.
+ gif = gif_open()
+ GIF_FD(gif) = IP_FD(ip)
+ fd = GIF_FD(gif)
+
+ # The GIF signature is verified in the database file but check it
+ # here anyway.
+ filepos = 1
+ call ip_lseek (fd, BOF)
+ if (gif_getbytes(fd, sig, 6) != OK)
+ call error (0, "Error reading GIF magic number.")
+ if (strncmp(sig[4],"87a",3) == 0)
+ version = 87
+ else if (strncmp(sig[4],"89a",3) == 0)
+ version = 89
+ else
+ call error (0, "Bad version: File is not a GIF 87a or 89A")
+
+ # Now read the screen descriptor.
+ if (gif_getbytes(fd, screen, 7) != OK)
+ call error (0, "Error reading screen descriptor.")
+
+ GIF_WIDTH(gif) = screen[1] + (256 * screen[2])
+ GIF_HEIGHT(gif) = screen[3] + (256 * screen[4])
+ GIF_BITPIX(gif) = shifti (2, and(int(screen[5]),07X))
+ GIF_COLRES(gif) = shifti (and(int(screen[5]), 070X), -3) + 1
+ GIF_BACKGROUND(gif) = screen[6]
+ GIF_ASPECT(gif) = screen[7]
+ if (DEBUG) {
+ call eprintf ("w:%d h:%d bpix:%d ncol:%d bkg:%d asp:%d\n")
+ call pargi(GIF_WIDTH(gif)); call pargi(GIF_HEIGHT(gif))
+ call pargi(GIF_BITPIX(gif)); call pargi(GIF_COLRES(gif))
+ call pargi(GIF_BACKGROUND(gif)); call pargi(GIF_ASPECT(gif))
+ call flush (STDERR)
+ }
+
+ # We'll set the buffer size to the full image to speed processing.
+ IP_SZBUF(ip) = GIF_HEIGHT(gif)
+
+ # See if we have a global colormap.
+ if (and (int(screen[5]), LOCAL_COLORMAP) > 0)
+ call gif_rdcmap (gif, GIF_BITPIX(gif), GIF_CMAP(gif))
+ IP_CMAP(ip) = GIF_CMAP(gif)
+
+ # Now process the rest of the image blocks.
+ GIF_IMNUM(gif) = 0
+ repeat {
+ if (gif_rdbyte(fd, ch) != OK) {
+ call error (0, "Bad data read.")
+ }
+
+ if (ch == ';') { # GIF terminator
+ break
+ }
+
+ if (ch == '!') { # Extension block
+ # Read the extension function code.
+ if (gif_rdbyte(fd, ch) != OK)
+ call error (0, "Bad data read.")
+ call gif_extension (gif, ch, IP_VERBOSE(ip))
+ next
+ }
+
+ if (ch != ',') { # not a valid start character
+ if (ch != '\0') { # quietly allow a NULL block
+ call eprintf ("Ignoring bogus start char 0x%02x.")
+ call pargc (ch)
+ }
+ next
+ }
+
+ # Read the current image descriptor block. There may be more
+ # than one image in a file so we'll just copy each image into
+ # a separate band of the output image (should be rare).
+ GIF_IMNUM(gif) = GIF_IMNUM(gif) + 1
+ if (gif_getbytes (fd, screen, 9) != OK)
+ call error (0, "Bad scene descriptor")
+
+ # See if this image has a local colormap. There supposedly aren't
+ # a lot of files that use this (GIF89a only) but we'll read it
+ # anyway so we don't get stung on file positioning.
+ if (and (int(screen[9]), LOCAL_COLORMAP) == LOCAL_COLORMAP)
+ use_global_cmap = NO
+ else
+ use_global_cmap = YES
+
+ # Unpack the image descriptor into useful things.
+ bitpix = shifti (1, (and (int(screen[9]), 07X) + 1))
+ interlace = btoi (and (int(screen[9]), INTERLACE) == INTERLACE)
+ width = screen[5] + (screen[6] * 256)
+ height = screen[7] + (screen[8] * 256)
+ if (DEBUG) {
+ call eprintf ("global_cmap:%d bitpix:%d ")
+ call pargi(use_global_cmap); call pargi(bitpix)
+ call eprintf ("interlace:%d w:%d h:%d\n")
+ call pargi(interlace); call pargi(width); call pargi(height)
+ }
+
+ if (info_only == NO) {
+ if (use_global_cmap == NO) {
+ # Process the image with a local colormap.
+ call gif_rdcmap (gif, bitpix, GIF_CMAP(gif))
+ call gif_read_image (ip, gif, width, height,
+ GIF_CMAP(gif), interlace)
+ } else {
+ # Process the image with the global colormap.
+ call gif_read_image (ip, gif, width, height,
+ GIF_CMAP(gif), interlace)
+ }
+ } else {
+ call ip_gif_info (ip, fname, version, width, height,
+ GIF_BITPIX(gif), use_global_cmap, interlace, verbose)
+ break
+ }
+ }
+
+ # Clean up.
+ call gif_close (gif)
+ IP_CMAP(ip) = NULL
+end
+
+
+# IP_GIF_INFO - Print information about the GIF file.
+
+procedure ip_gif_info (ip, fname, version, width, height, colres, global,
+ interlace, verbose)
+
+pointer ip #i task struct pointer
+char fname[ARB] #i file name
+int version #i GIF version
+int width, height #i image dimensions
+int colres #i number of colormap entries
+int global #i image has global colormap
+int interlace #i image is interlaced
+int verbose #i verbosity flag
+
+begin
+ # If not verbose print a one-liner.
+ if (verbose == NO) {
+# call printf ("Input file:\n\t")
+ call printf ("%s: %20t%d x %d \t\tCompuServe GIF %da format file\n")
+ call pargstr (fname)
+ call pargi (width)
+ call pargi (height)
+ call pargi (version)
+
+ # Print out the format comment if any.
+# if (IP_COMPTR(ip) != NULL) {
+# if (COMMENT(ip) != '\0') {
+# call printf ("%s\n")
+# call pargstr (COMMENT(ip))
+# }
+# call strcpy ("\0", COMMENT(ip), SZ_LINE)
+# }
+ return
+ }
+
+ # Print a more verbose description.
+ call printf ("%s: %20tCompuServe GIF %da Format File\n")
+ call pargstr (fname)
+ call pargi (version)
+
+ # Print out the format comment if any.
+ if (IP_COMPTR(ip) != NULL) {
+ if (COMMENT(ip) != '\0') {
+ call printf ("%s\n")
+ call pargstr (COMMENT(ip))
+ }
+ call strcpy ("\0", COMMENT(ip), SZ_LINE)
+ }
+
+ call printf ("%20tResolution:%38t%d x %d\n")
+ call pargi (width)
+ call pargi (height)
+
+ call printf ("%20tPixel storage: %38t%s\n")
+ if (interlace == YES)
+ call pargstr ("Interlaced order")
+ else
+ call pargstr ("Sequential order")
+
+ call printf ("%20tByte Order: %38t%s\n")
+ call pargstr ("LSB first")
+
+ call printf ("%20tType: %38t%s\n")
+ call pargstr ("8-bit Color indexed")
+
+ call printf ("%20t%s Colormap: %38t%d entries\n")
+ if (global == YES)
+ call pargstr ("Global")
+ else
+ call pargstr ("Local")
+ call pargi (colres)
+
+ call printf ("%20tCompression: %38t%s\n")
+ call pargstr ("Lempel-Ziv and Welch (LZW)")
+end
+
+
+# GIF_OPEN - Open the GIF structure descriptor.
+
+pointer procedure gif_open ()
+
+pointer gif
+
+begin
+ iferr (call calloc (gif, SZ_GIFSTRUCT, TY_STRUCT))
+ call error (0, "Error allocating GIF structure.")
+
+ # Allocate the extension and code buffers.
+ iferr (call calloc (GIF_CODEP(gif), SZ_GIFCODE, TY_CHAR))
+ call error (0, "Error allocating GIF code buffer pointer.")
+ iferr (call calloc (GIF_EXTBP(gif), SZ_GIFEXTN, TY_CHAR))
+ call error (0, "Error allocating GIF extension pointer.")
+ iferr (call calloc (GIF_CTABP(gif), SZ_GIFCTAB, TY_CHAR))
+ call error (0, "Error allocating code table pointer.")
+ iferr (call calloc (GIF_STACKP(gif), SZ_GIFSTACK, TY_CHAR))
+ call error (0, "Error allocating GIF stack pointer.")
+
+ # Initialize some of the variables to non-zero values.
+ GIF_ZERO_DATABLOCK(gif) = NO
+ GIF_TRANSPARENT(gif) = -1
+ GIF_DELAYTIME(gif) = -1
+ GIF_INPUTFLAG(gif) = -1
+
+ return (gif)
+end
+
+
+# GIF_CLOSE - Close the GIF structure descriptor.
+
+procedure gif_close (gif)
+
+pointer gif #i GIF struct pointer
+
+begin
+ call mfree (GIF_STACKP(gif), TY_CHAR)
+ call mfree (GIF_CTABP(gif), TY_CHAR)
+ call mfree (GIF_EXTBP(gif), TY_CHAR)
+ call mfree (GIF_CODEP(gif), TY_CHAR)
+
+ if (GIF_CMAP(gif) != NULL)
+ call mfree (GIF_CMAP(gif), TY_CHAR)
+ call mfree (gif, TY_STRUCT)
+end
+
+
+# GIF_READ_IMAGE - Read the image raster from the file. Decompress the
+# LZW compressed data stream into 8-bit pixels.
+
+procedure gif_read_image (ip, gif, width, height, cmap, interlace)
+
+pointer ip #i task struct pointer
+pointer gif #i GIF struct pointer
+int width, height #i image dimensions
+pointer cmap #i colormap pointer
+int interlace #i interlace flag
+
+pointer im, op, out, data
+char csize, pix, val
+int i, v, xpos, ypos, pass
+int nlines, line, percent
+
+pointer ip_evaluate()
+int gif_rdbyte(), gif_lzw_rdbyte()
+short ip_gcmap_val()
+
+begin
+ # Get the initial code_size for the compression routines.
+ if (gif_rdbyte(GIF_FD(gif), csize) != OK)
+ call error (0, "EOF or read error on image data.")
+ call gif_lzw_init (gif, csize)
+
+ # Patch up the pixtype param if needed.
+ call ip_fix_pixtype (ip)
+
+ # See if we need to create any outbands operands if the user didn't.
+ if (IP_NBANDS(ip) == ERR)
+ call ip_fix_outbands (ip)
+
+ im = IP_IM(ip)
+ op = PTYPE(ip,GIF_IMNUM(gif))
+ call malloc (data, width, TY_CHAR)
+ IO_DATA(op) = data
+ IO_NPIX(op) = width
+
+ # Get the pixels.
+ xpos = 0
+ ypos = 0
+ pass = 0
+ nlines = 0
+ percent = 0
+ repeat {
+ v = gif_lzw_rdbyte (gif)
+ if (v < 0)
+ break # at the EOF
+ else {
+ if (cmap != NULL && IP_USE_CMAP(ip) == YES) {
+ # Apply the colormap since this is just an index.
+ val = v + 1
+ pix = ip_gcmap_val (val, cmap)
+ } else
+ pix = char (v)
+ Memc[data+xpos] = pix # assign the pixel
+ }
+
+ xpos = xpos + 1
+ if (xpos == width) {
+ xpos = 0
+ nlines = nlines + 1
+
+ # Evaluate outbands expression.
+ do i = 1, IP_NBANDS(ip) {
+ out = ip_evaluate (ip, O_EXPR(ip,i))
+
+ # Write bands to output image
+ if (IP_OUTPUT(ip) != IP_NONE) {
+ line = ypos + 1
+ call ip_wrline (ip, im, out, GIF_WIDTH(gif), line,
+ (GIF_IMNUM(gif)-1)*IP_NBANDS(ip)+i)
+ }
+ call evvfree (out)
+ }
+
+ # Print percent done if being verbose
+ if (IP_VERBOSE(ip) == YES) {
+ if (nlines * 100 / height >= percent + 10) {
+ percent = percent + 10
+ call printf (" Status: %2d%% complete\r")
+ call pargi (percent)
+ call flush (STDOUT)
+ }
+ }
+
+ # if the image is interlaced adjust the line number accordingly,
+ # otherwise just increment it.
+ if (interlace == YES) {
+ switch (pass) {
+ case 0, 1:
+ ypos = ypos + 8
+ case 2:
+ ypos = ypos + 4
+ case 3:
+ ypos = ypos + 2
+ }
+
+ if (ypos >= height) {
+ pass = pass + 1
+ switch (pass) {
+ case 1:
+ ypos = 4
+ case 2:
+ ypos = 2
+ case 3:
+ ypos = 1
+ }
+ }
+ } else {
+ # Non-interlaced GIF so just increment the line number.
+ ypos = ypos + 1
+ }
+ }
+ }
+
+ if (IP_VERBOSE(ip) == YES) {
+ call printf (" Status: Done \n")
+ call flush (STDOUT)
+ }
+
+ # Clean up the data pointer.
+ call mfree (data, TY_CHAR)
+end
+
+
+# GIF_RDCMAP - Read a colormap (local or global) from the GIF file.
+
+procedure gif_rdcmap (gif, ncolors, cmap)
+
+pointer gif #i GIF struct pointer
+int ncolors #i number of colors to read
+pointer cmap #u local or global colormap ptr
+
+int i
+char rgb[3]
+int gif_getbytes()
+
+begin
+ if (cmap == NULL)
+ iferr (call calloc (cmap, 3*CMAP_SIZE, TY_CHAR))
+ call error (0, "Error allocating color map.")
+
+ do i = 1, ncolors {
+ # Read RGB colors.
+ if (gif_getbytes (GIF_FD(gif), rgb, 3) != OK)
+ call error (0, "Bad GIF colormap - not enough colors.")
+
+ # Load the colormap.
+ CMAP(cmap,IP_RED,i) = rgb[1]
+ CMAP(cmap,IP_GREEN,i) = rgb[2]
+ CMAP(cmap,IP_BLUE,i) = rgb[3]
+ }
+end
+
+
+# GIF_EXTENSION - Process a GIF extension block. For now we'll just ignore
+# these when converting the image but read the data blocks anyway. We should
+# still be able to read the image but won't take advantage of the GIF89a
+# extensions.
+
+procedure gif_extension (gif, label, verbose)
+
+pointer gif #i Gif struct pointer
+char label #i GIF extension label
+int verbose #i print verbose info?
+
+pointer sp, buf
+int val
+int and(), gif_get_data_block()
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_GIFCODE, TY_CHAR)
+
+ switch (label) {
+ case GE_PLAINTEXT: # Plain Text Extension
+ if (verbose == YES) {
+ call eprintf ("Warning: Ignoring a Plain Text Extension.\n")
+ call flush (STDERR)
+ }
+ case GE_APPLICATION: # Application Extension
+ if (verbose == YES) {
+ call eprintf ("Warning: Ignoring an Application Extension.\n")
+ call flush (STDERR)
+ }
+ case GE_COMMENT: # Comment Extension
+ # Simply print out the comment.
+ while (gif_get_data_block (gif, Memc[buf]) != 0) {
+ if (verbose == YES) {
+ call printf ("Comment: %s\n")
+ call pargstr (Memc[buf])
+ }
+ }
+ call sfree (sp)
+ return
+ case GE_GCONTROL: # Graphic Control Extension
+ # Process the graphic control block.
+ val = gif_get_data_block (gif, Memc[buf])
+ GIF_DISPOSAL(gif) = and (int(Memc[buf]/4), 07X)
+ GIF_INPUTFLAG(gif) = and (int(Memc[buf]/2), 01X)
+ GIF_DELAYTIME(gif) = Memc[buf+1] + (256 * Memc[buf+2])
+ if (and(int(Memc[buf]),01X) == 1)
+ GIF_TRANSPARENT(gif) = Memc[buf+3]
+
+ while (gif_get_data_block (gif, Memc[buf]) != 0)
+ ;
+
+ call sfree (sp)
+ return
+ default:
+ call eprintf ("Warning: Unknown extension label (0x%02x).\n")
+ call pargc (label)
+ call flush (STDERR)
+ }
+
+ # If we get here then we've ignored an extension but still need to
+ # eat the data blocks.
+ while (gif_get_data_block (gif, Memc[buf]) != 0)
+ ;
+
+ call sfree (sp)
+end
+
+
+# GIF_LZW_INIT - Initialize the LZW decompression variables.
+
+procedure gif_lzw_init (gif, input_code_size)
+
+pointer gif #i GIF struct pointer
+char input_code_size #i input code size
+
+int i, shifti()
+
+begin
+ GIF_SET_CODE_SIZE(gif) = input_code_size
+ GIF_CODE_SIZE(gif) = GIF_SET_CODE_SIZE(gif) + 1
+ GIF_CLEAR_CODE(gif) = shifti (1, GIF_SET_CODE_SIZE(gif))
+ GIF_END_CODE(gif) = GIF_CLEAR_CODE(gif) + 1
+ GIF_MAX_CODE_SIZE(gif) = 2 * GIF_CLEAR_CODE(gif)
+ GIF_MAX_CODE(gif) = GIF_CLEAR_CODE(gif) + 2
+
+ GIF_CURBIT(gif) = 0 # initialize the code vars
+ GIF_LASTBIT(gif) = 0
+ GIF_DONE(gif) = NO
+
+ GIF_FRESH(gif) = YES
+
+ # Initialize the code table.
+ for (i = 0; i < GIF_CLEAR_CODE(gif); i=i+1) {
+ CODETAB(gif,0,i) = 0
+ CODETAB(gif,1,i) = i
+ }
+ for (; i < MAX_CODE_ENTRIES; i=i+1) {
+ CODETAB(gif,0,i) = 0
+ CODETAB(gif,1,0) = 0
+ }
+
+ GIF_SP(gif) = 0
+end
+
+
+
+# GIF_LZW_RDBYTE -
+
+int procedure gif_lzw_rdbyte (gif)
+
+pointer gif #i GIF struct pointer
+
+pointer sp, buf
+int i, count
+int code, incode
+
+int gif_get_code(), gif_get_data_block()
+
+begin
+ if (GIF_FRESH(gif) == YES) {
+ GIF_FRESH(gif) = NO
+ repeat {
+ GIF_OLD_CODE(gif) = gif_get_code (gif, GIF_CODE_SIZE(gif))
+ GIF_FIRST_CODE(gif) = GIF_OLD_CODE(gif)
+ } until (GIF_FIRST_CODE(gif) != GIF_CLEAR_CODE(gif))
+ return (GIF_FIRST_CODE(gif))
+ }
+
+ if (GIF_SP(gif) > 0) {
+ GIF_SP(gif) = GIF_SP(gif) - 1
+ return (STACK(gif,GIF_SP(gif)))
+ }
+
+ code = gif_get_code (gif, GIF_CODE_SIZE(gif))
+ while (code >= 0) {
+
+ # The Clear Code sets everything back to its initial value, then
+ # reads the immediately subsequent code as uncompressed data.
+ if (code == GIF_CLEAR_CODE(gif)) {
+ for (i = 0; i < GIF_CLEAR_CODE(gif); i=i+1) {
+ CODETAB(gif,0,i) = 0
+ CODETAB(gif,1,i) = i
+ }
+ for ( ; i < MAX_CODE_ENTRIES; i=i+1) {
+ CODETAB(gif,0,i) = 0
+ CODETAB(gif,1,i) = 0
+ }
+ GIF_CODE_SIZE(gif) = GIF_SET_CODE_SIZE(gif) + 1
+ GIF_MAX_CODE_SIZE(gif) = 2 * GIF_CLEAR_CODE(gif)
+ GIF_MAX_CODE(gif) = GIF_CLEAR_CODE(gif) + 2
+ GIF_SP(gif) = 0
+ GIF_OLD_CODE(gif) = gif_get_code (gif, GIF_CODE_SIZE(gif))
+ GIF_FIRST_CODE(gif) = GIF_OLD_CODE(gif)
+ return (GIF_FIRST_CODE(gif))
+
+ # If this is the End Code we'll clean up a little before returning.
+ } else if (code == GIF_END_CODE(gif)) {
+ if (GIF_ZERO_DATABLOCK(gif) == YES)
+ return (ERR)
+
+ call smark (sp)
+ call salloc (buf, 260, TY_CHAR)
+
+ repeat {
+ count = gif_get_data_block (gif, Memc[buf])
+ } until (count <= 0)
+
+ if (count != 0) {
+ call eprintf (
+ "Missing EOD in data stream (common occurance)")
+ }
+ call sfree (sp)
+ return (ERR)
+ }
+
+ # Must be data so save it in incode.
+ incode = code
+
+ # If it's greater or equal than the Free Code it's not in the hash
+ # table yet, repeat the last character decoded.
+ if (code >= GIF_MAX_CODE(gif)) {
+ STACK(gif, GIF_SP(gif)) = GIF_FIRST_CODE(gif)
+ GIF_SP(gif) = GIF_SP(gif) + 1
+ code = GIF_OLD_CODE(gif)
+ }
+
+ while (code >= GIF_CLEAR_CODE(gif)) {
+ STACK(gif, GIF_SP(gif)) = CODETAB(gif,1,code)
+ GIF_SP(gif) = GIF_SP(gif) + 1
+ if (code == CODETAB(gif,0,code))
+ call error (0, "Circular GIF code table entry.")
+ code = CODETAB(gif,0,code)
+ }
+
+ GIF_FIRST_CODE(gif) = CODETAB(gif,1,code)
+ STACK(gif, GIF_SP(gif)) = GIF_FIRST_CODE(gif)
+ GIF_SP(gif) = GIF_SP(gif) + 1
+
+ if (VDEBUG) {
+ call eprintf("code=%d gmax=%d gmaxsz=%d 4096 old:%d frst:%d\n")
+ call pargi(code) ; call pargi(GIF_MAX_CODE(gif))
+ call pargi(GIF_MAX_CODE_SIZE(gif))
+ call pargi(GIF_OLD_CODE(gif))
+ call pargi(GIF_FIRST_CODE(gif))
+ }
+
+ # Point to the next slot in the table. If we exceed the current
+ # MaxCode value, increment the code size unless it's already 12.
+ # If it is, do nothing: the next code decompressed better be CLEAR
+
+ code = GIF_MAX_CODE(gif)
+ if (code < MAX_CODE_ENTRIES) {
+ CODETAB(gif,0,code) = GIF_OLD_CODE(gif)
+ CODETAB(gif,1,code) = GIF_FIRST_CODE(gif)
+ GIF_MAX_CODE(gif) = GIF_MAX_CODE(gif) + 1
+ if ((GIF_MAX_CODE(gif) >= GIF_MAX_CODE_SIZE(gif)) &&
+ (GIF_MAX_CODE_SIZE(gif) < MAX_CODE_ENTRIES)) {
+ GIF_MAX_CODE_SIZE(gif) = GIF_MAX_CODE_SIZE(gif) * 2
+ GIF_CODE_SIZE(gif) = GIF_CODE_SIZE(gif) + 1
+ }
+ }
+
+ GIF_OLD_CODE(gif) = incode
+
+ if (GIF_SP(gif) > 0) {
+ GIF_SP(gif) = GIF_SP(gif) - 1
+ return (STACK(gif,GIF_SP(gif)))
+ }
+
+ code = gif_get_code (gif, GIF_CODE_SIZE(gif))
+ }
+ return code
+end
+
+
+# GIF_GET_CODE - Fetch the next code from the raster data stream. The codes
+# can be any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
+# maintain our location in the Raster array as a BIT Offset. We compute the
+# byte Offset into the raster array by dividing this by 8, pick up three
+# bytes, compute the bit Offset into our 24-bit chunk, shift to bring the
+# desired code to the bottom, then mask it off and return it. Simple.
+
+int procedure gif_get_code (gif, code_size)
+
+pointer gif #i GIF struct pointer
+int code_size #i op code size
+
+int i, j, count, ret
+int val1, val2
+int btoi(), and(), shifti(), ori ()
+int gif_get_data_block()
+
+begin
+ # See if processing the next code will overflow our buffer. If so
+ # we get the next control block from the stream.
+ if ( (GIF_CURBIT(gif) + code_size) >= GIF_LASTBIT(gif)) {
+ if (GIF_DONE(gif) == YES) {
+ if (GIF_CURBIT(gif) >= GIF_LASTBIT(gif)) {
+ call error (0, "GIF_GET_CODE: Ran out of bits.\n")
+ return (ERR)
+ }
+ }
+
+ CODEBUF(gif,0) = CODEBUF(gif,GIF_LASTBYTE(gif)-2)
+ CODEBUF(gif,1) = CODEBUF(gif,GIF_LASTBYTE(gif)-1)
+
+ count = gif_get_data_block (gif, CODEBUF(gif,2))
+ if (count == 0)
+ GIF_DONE(gif) = YES
+
+ GIF_LASTBYTE(gif) = 2 + count
+ GIF_CURBIT(gif) = (GIF_CURBIT(gif) - GIF_LASTBIT(gif)) + 16
+ GIF_LASTBIT(gif) = (2 + count) * 8
+ }
+
+ # for (i = GIF_CURBIT(gif), j = 0; j < code_size; ++i, ++j)
+ # ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
+
+ i = GIF_CURBIT(gif)
+ j = 0
+ ret = 0
+ while (j < code_size) {
+ val1 = btoi ( and (int(CODEBUF(gif,i/8)), shifti(1,mod(i,8))) != 0 )
+ val2 = shifti (val1, j)
+ ret = ori (ret, val2)
+ i = i + 1
+ j = j + 1
+ }
+
+ GIF_CURBIT(gif) = GIF_CURBIT(gif) + code_size
+ if (VDEBUG) {
+ call eprintf (": returning %d\n");call pargi(ret);call flush(STDERR)
+ }
+
+ return (ret)
+end
+
+
+# GIF_GET_DATA_BLOCK - Get the next block of GIF data from the data stream so
+# it can be converted to raster data.
+
+int procedure gif_get_data_block (gif, buf)
+
+pointer gif #i GIF struct pointer
+char buf[ARB] #o data block
+
+char count
+int nb, btoi()
+int gif_rdbyte(), gif_getbytes()
+
+begin
+ if (gif_rdbyte (GIF_FD(gif), count) != OK) {
+ call error (0, "error in getting DataBlock size")
+ return (ERR)
+ }
+
+ GIF_ZERO_DATABLOCK(gif) = btoi (count == 0)
+ if (VDEBUG) {
+ call eprintf ("getDataBlock: count = %d "); call pargs(count) }
+ nb = count
+ if ((count != 0) && (gif_getbytes(GIF_FD(gif), buf, nb) != OK)) {
+ call error (0, "error in reading DataBlock")
+ return (ERR)
+ }
+ return count
+end
+
+
+
+# Byte I/O routines. We use the normal IMPORT procedures but localize the code
+# here to make it easier to keep track of the current file position (in bytes).
+
+# GIF_RDBYTE - Read a single byte at the current offset from the file.
+
+int procedure gif_rdbyte (fd, val)
+
+int fd #i file descriptor
+char val #o byte read
+
+short ip_getb()
+
+long filepos
+common /gifcom/ filepos
+
+begin
+ iferr (val = ip_getb (fd, filepos))
+ return (ERR)
+
+ filepos = filepos + 1
+ call ip_lseek (fd, filepos)
+
+ return (OK)
+end
+
+
+# GIF_GETBYTES - Read an array of bytes from the file at the current offset.
+
+int procedure gif_getbytes (fd, buffer, len)
+
+int fd #i file descriptor
+char buffer[ARB] #o output buffer
+int len #i no. of bytes to read
+
+pointer sp, bp
+
+long filepos
+common /gifcom/ filepos
+
+begin
+ call smark (sp)
+ call salloc (bp, len+1, TY_CHAR)
+ call aclrc (Memc[bp], len+1)
+
+ call ip_agetb (fd, bp, len) # read the bytes
+ call amovc (Memc[bp], buffer, len) # copy to output buffer
+ filepos = filepos + len
+ call ip_lseek (fd, filepos)
+
+ call sfree (sp)
+ return (OK)
+end
diff --git a/pkg/dataio/import/bltins/ipras.x b/pkg/dataio/import/bltins/ipras.x
new file mode 100644
index 00000000..100ca6dc
--- /dev/null
+++ b/pkg/dataio/import/bltins/ipras.x
@@ -0,0 +1,504 @@
+include <mach.h>
+include "../import.h"
+
+
+# IPRAS.X - Source file for the IMPORT task rasterfile builtin format.
+
+
+define SZ_RASHDR 13
+define RAS_MAGIC Memi[$1] # Magic number
+define RAS_WIDTH Memi[$1+1] # Image width (pixels per line)
+define RAS_HEIGHT Memi[$1+2] # Image height (number of lines)
+define RAS_DEPTH Memi[$1+3] # Image depth (bits per pixel)
+define RAS_LENGTH Memi[$1+4] # Image length (bytes)
+define RAS_TYPE Memi[$1+5] # File type
+define RAS_MAPTYPE Memi[$1+6] # Colormap type
+define RAS_MAPLENGTH Memi[$1+7] # Colormap length (bytes)
+
+define RAS_CMAP Memi[$1+10] # Colormap (ptr)
+define RAS_COUNT Memi[$1+11] # RLE decoding var
+define RAS_CH Memi[$1+12] # RLE decoding var
+
+# Rasterfile magic number
+define RAS_MAGIC_NUM 59A66A95X
+define RAS_RLE 80X
+
+# Sun supported ras_types
+define RT_OLD 0 # Raw pixrect image in 68000 byte order
+define RT_STANDARD 1 # Raw pixrect image in 68000 byte order
+define RT_BYTE_ENCODED 2 # Run-length compression of bytes
+define RT_FORMAT_RGB 3 # XRGB or RGB instead of XBGR or BGR
+define RT_FORMAT_TIFF 4 # tiff <-> standard rasterfile
+define RT_FORMAT_IFF 5 # iff (TAAC format) <-> standard rasterfile
+define RT_EXPERIMENTAL 65535 # Reserved for testing
+
+# Sun supported ras_maptypes
+define RMT_NONE 0 # ras_maplength is expected to be 0
+define RMT_EQUAL_RGB 1 # red[ras_maplength/3],green[],blue[]
+define RMT_RAW 2
+
+
+
+# IP_RAS - Read and process a Sun Rasterfile into an IRAF image.
+
+procedure ip_ras (ip, fname, info_only, verbose)
+
+pointer ip #i import struct pointer
+char fname[ARB] #i file name
+int info_only #i print out image info only?
+int verbose #i verbosity flag
+
+pointer ras
+int fd, w, nchars
+pointer ras_open()
+
+long filepos
+common /rascom/ filepos
+
+begin
+ # Allocate the ras struct pointer.
+ ras = ras_open ()
+ fd = IP_FD(ip)
+
+ # Initialize the file position.
+ filepos = 1
+ call ip_lseek (fd, BOF)
+
+ # Read in the rasterfile header, dump it directly to the task struct.
+ call ip_ageti (fd, ras, 8)
+ filepos = filepos + SZ_INT32 * SZB_CHAR * 8
+ call ip_lseek (fd, filepos)
+
+ # Now do some sanity checking on the values.
+ if (RAS_MAGIC(ras) != RAS_MAGIC_NUM)
+ call error (0, "Not a Sun rasterfile.")
+ if (RAS_TYPE(ras) == RT_OLD && RAS_LENGTH(ras) == 0)
+ RAS_LENGTH(ras) = RAS_WIDTH(ras) * RAS_HEIGHT(ras) *
+ RAS_DEPTH(ras) / 8
+
+ # See if we really want to convert this thing.
+ if (info_only == YES) {
+ call ip_ras_info (ip, ras, fname, verbose)
+ call ras_close (ras)
+ return
+ }
+
+ # Get the colormap (if any).
+ call ras_rdcmap (fd, ras, RAS_CMAP(ras))
+ IP_CMAP(ip) = RAS_CMAP(ras)
+
+ # Round up to account for 16 bit line blocking.
+ w = RAS_WIDTH(ras) * (RAS_DEPTH(ras) / 8)
+ nchars = w + mod (w, SZB_CHAR)
+
+
+ # Patch up the pixtype param if needed.
+ call ip_fix_pixtype (ip)
+
+ # See if we need to create any outbands operands if the user didn't.
+ if (IP_NBANDS(ip) == ERR)
+ call ip_fix_outbands (ip)
+
+ # Now process the image.
+ switch (RAS_DEPTH(ras)) {
+ case 1:
+ call eprintf ("Bitmap rasterfiles aren not supported.")
+ call flush (STDERR)
+
+ case 8:
+ # Standard or byte encoded 8-bit rasterfile.
+ if (RAS_TYPE(ras) == RT_OLD || RAS_TYPE(ras) == RT_STANDARD) {
+ call ip_prband (ip, fd, IP_IM(ip), RAS_CMAP(ras))
+
+ } else if (RAS_TYPE(ras) == RT_BYTE_ENCODED) {
+ call ras_rle8 (ip, ras, fd, nchars)
+
+ } else {
+ call eprintf ("Unsupported 8-bit RAS_TYPE: %d\n")
+ call pargi (RAS_TYPE(ras))
+ call flush (STDERR)
+ }
+
+ case 24, 32:
+ # 24 or 32-bit rasterfiles have no colormap (at least they
+ # shouldn't) and are pixel-interleaved. We already know how to
+ # do this so just call the right routines for processing.
+
+ if (RAS_TYPE(ras) == RT_BYTE_ENCODED) {
+ call ip_fix_pixtype (ip)
+ call ras_rle24 (ip, ras, fd, nchars)
+ } else {
+ call ip_fix_pixtype (ip)
+ call ip_prpix (ip, fd, IP_IM(ip), NULL)
+ }
+
+ default:
+ call eprintf ("Invalid pixel size.")
+ call flush (STDERR)
+ }
+
+ # Clean up.
+ call ras_close (ras)
+ IP_CMAP(ip) = NULL
+end
+
+
+# IP_RAS_INFO - Print information about the raster file.
+
+procedure ip_ras_info (ip, ras, fname, verbose)
+
+pointer ip #i ip struct pointer
+pointer ras #i ras struct pointer
+char fname[ARB] #i file name
+int verbose #i verbosity flag
+
+begin
+ # If not verbose print a one-liner.
+ if (verbose == NO) {
+# call printf ("Input file:\n\t")
+ call printf ("%s: %20t%d x %d \t\t%d-bit Sun Rasterfile\n")
+ call pargstr (fname)
+ call pargi (RAS_WIDTH(ras))
+ call pargi (RAS_HEIGHT(ras))
+ call pargi (RAS_DEPTH(ras))
+
+ # Print out the format comment if any.
+# if (IP_COMPTR(ip) != NULL) {
+# if (COMMENT(ip) != '\0') {
+# call printf ("%s\n")
+# call pargstr (COMMENT(ip))
+# }
+# call strcpy ("\0", COMMENT(ip), SZ_LINE)
+# }
+# if (RAS_DEPTH(ras) > 8) {
+# if (RAS_TYPE(ras) != RT_FORMAT_RGB && RAS_TYPE(ras) != RT_OLD) {
+# call eprintf ("\tNote: %d-bit rasterfile is stored as %s\n")
+# call pargi (RAS_DEPTH(ras))
+# call pargstr ("ABGR and not ARGB")
+# }
+# }
+ return
+ }
+
+ # Print a more verbose description.
+ call printf ("%s: %20tSun Rasterfile\n")
+ call pargstr (fname)
+
+ # Print out the format comment if any.
+ if (IP_COMPTR(ip) != NULL) {
+ if (COMMENT(ip) != '\0') {
+ call printf ("%s\n")
+ call pargstr (COMMENT(ip))
+ }
+ call strcpy ("\0", COMMENT(ip), SZ_LINE)
+ }
+ if (RAS_DEPTH(ras) > 8) {
+ if (RAS_TYPE(ras) != RT_FORMAT_RGB && RAS_TYPE(ras) != RT_OLD) {
+ call eprintf ("\tNote: %d-bit rasterfile is stored as %s\n")
+ call pargi (RAS_DEPTH(ras))
+ call pargstr ("ABGR and not ARGB")
+ }
+ }
+
+ call printf ("%20tByte Order:%38t%s\n")
+ if (IP_SWAP(ip) == S_NONE && BYTE_SWAP2 == NO )
+ call pargstr ("Most Significant Byte First")
+ else
+ call pargstr ("Least Significant Byte First")
+
+ call printf ("%20tResolution:%38t%d x %d\n")
+ call pargi (RAS_WIDTH(ras))
+ call pargi (RAS_HEIGHT(ras))
+
+ call printf ("%20tType: %38t%d-bit %s %s\n")
+ call pargi (RAS_DEPTH(ras))
+ switch (RAS_TYPE(ras)) {
+ case RT_OLD:
+ call pargstr ("Old")
+ case RT_STANDARD:
+ call pargstr ("Standard")
+ case RT_BYTE_ENCODED:
+ call pargstr ("Byte Encoded")
+ case RT_FORMAT_RGB:
+ call pargstr ("RGB")
+ case RT_FORMAT_TIFF:
+ call pargstr ("TIFF")
+ case RT_FORMAT_IFF:
+ call pargstr ("IFF")
+ default:
+ call pargstr ("Experimental (or unknown)")
+ }
+ if (RAS_MAPLENGTH(ras) > 0)
+ call pargstr ("Color Index")
+ else
+ call pargstr ("")
+
+ if (RAS_MAPLENGTH(ras) > 0) {
+ call printf ("%20tColormap:%38t%d entries\n")
+ if (RAS_MAPTYPE(ras) == RMT_EQUAL_RGB)
+ call pargi (RAS_MAPLENGTH(ras)/3)
+ else
+ call pargi (RAS_MAPLENGTH(ras))
+ } else
+ call printf ("%20tColormap:%38tnone\n")
+
+ call printf ("%20tCompression: %38t%s\n")
+ if (RAS_TYPE(ras) == RT_BYTE_ENCODED)
+ call pargstr ("Run Length Encoded")
+ else
+ call pargstr ("None")
+
+ call printf ("%20tAlpha Channel: %38t%s\n")
+ if (RAS_DEPTH(ras) == 32)
+ call pargstr ("yes")
+ else
+ call pargstr ("none")
+end
+
+
+# RAS_OPEN - Open the RAS structure descriptor.
+
+pointer procedure ras_open ()
+
+pointer ras
+
+begin
+ iferr (call calloc (ras, SZ_RASHDR, TY_STRUCT))
+ call error (0, "Error allocating RAS structure.")
+ RAS_CMAP(ras) = NULL
+
+ return (ras)
+end
+
+
+# RAS_CLOSE - Close the RAS structure descriptor.
+
+procedure ras_close (ras)
+
+pointer ras #i RAS struct pointer
+
+begin
+ if (RAS_CMAP(ras) != NULL)
+ call mfree (RAS_CMAP(ras), TY_CHAR)
+ call mfree (ras, TY_STRUCT)
+end
+
+
+# RAS_RDCMAP - Read the colormap from the image if necessary.
+
+procedure ras_rdcmap (fd, ras, cmap)
+
+int fd #i file descriptor
+pointer ras #i RAS struct pointer
+pointer cmap #i colormap array ptr
+
+int ncolors
+
+long filepos
+common /rascom/ filepos
+
+begin
+ # Now read the colormap, allocate the pointer if we need to.
+ ncolors = RAS_MAPLENGTH(ras)
+ if (RAS_MAPTYPE(ras) == RMT_EQUAL_RGB && ncolors > 0) {
+ if (cmap == NULL)
+ call calloc (cmap, ncolors*3, TY_CHAR)
+ call ip_agetb (fd, cmap, ncolors)
+
+ } else if (RAS_MAPTYPE(ras) == RMT_RAW) {
+ call eprintf ("Warning: Can't handle RMT_RAW maptype - ignoring.\n")
+ call flush (STDERR)
+
+ # Skip over the bytes anyway.
+ filepos = filepos + ncolors
+ call ip_lseek (fd, filepos)
+ return
+ }
+
+ filepos = filepos + ncolors
+ call ip_lseek (fd, filepos)
+end
+
+
+# RAS_RLE8 - Process an 8-bit rasterfile into an IRAF image. This
+# procedure handles both standard and RLE files.
+
+procedure ras_rle8 (ip, ras, fd, nchars)
+
+pointer ip #i ip struct pointer
+pointer ras #i ras struct pointer
+int fd #i input file descriptor
+int nchars #i line size
+
+pointer im, data, op
+int i, percent
+
+long filepos
+common /rascom/ filepos
+
+begin
+ im = IP_IM(ip)
+ op = PTYPE(ip,1)
+ call malloc (data, nchars, TY_CHAR)
+ IO_DATA(op) = data
+ IO_NPIX(op) = RAS_WIDTH(ras)
+
+ percent = 0
+ do i = 1, RAS_HEIGHT(ras) {
+ call ras_read_rle (ras, fd, Memc[data], nchars)
+
+ # Apply the colormap since this is just an index.
+ if (RAS_MAPLENGTH(ras) != 0 && IP_USE_CMAP(ip) == YES)
+ call ip_gray_cmap (Memc[data], RAS_WIDTH(ras),
+ RAS_CMAP(ras))
+
+ # Evaluate and write the outbands expressions.
+ call ip_probexpr (ip, im, RAS_WIDTH(ras), i)
+
+ # Print percent done if being verbose
+ if (IP_VERBOSE(ip) == YES) {
+ if (i * 100 / RAS_HEIGHT(ras) >= percent + 10) {
+ percent = percent + 10
+ call printf (" Status: %2d%% complete\r")
+ call pargi (percent)
+ call flush (STDOUT)
+ }
+ }
+
+ }
+
+ if (IP_VERBOSE(ip) == YES) {
+ call printf (" Status: Done \n")
+ call flush (STDOUT)
+ }
+end
+
+
+# RAS_RLE24 - Process an 24-bit rasterfile into an IRAF image. This
+# procedure handles both standard and RLE files.
+
+procedure ras_rle24 (ip, ras, fd, nchars)
+
+pointer ip #i ip struct pointer
+pointer ras #i ras struct pointer
+int fd #i input file descriptor
+int nchars #i line size
+
+pointer im, data, op
+int i, percent, npix
+
+long filepos
+common /rascom/ filepos
+
+begin
+ im = IP_IM(ip)
+ op = PTYPE(ip,1)
+ call malloc (data, nchars, TY_SHORT)
+ IO_DATA(op) = data
+ IO_NPIX(op) = RAS_WIDTH(ras)
+
+ # See if we need to create any outbands operands if the user didn't.
+ if (IP_NBANDS(ip) == ERR)
+ call ip_fix_outbands (ip)
+
+ # Allocate the pixtype data pointers.
+ npix = RAS_WIDTH(ras)
+ do i = 1, IP_NPIXT(ip) {
+ op = PTYPE(ip,i)
+ IO_NPIX(op) = npix
+ call calloc (IO_DATA(op), npix, TY_SHORT)
+ }
+
+ percent = 0
+ do i = 1, RAS_HEIGHT(ras) {
+ call ras_read_rle (ras, fd, Memc[data], nchars)
+
+ # Separate pixels into different vectors.
+ call ip_upkpix (ip, data, npix)
+
+ # Evaluate and write the outbands expressions.
+ call ip_probexpr (ip, im, npix, i)
+
+ # Print percent done if being verbose
+ if (IP_VERBOSE(ip) == YES) {
+ if (i * 100 / RAS_HEIGHT(ras) >= percent + 10) {
+ percent = percent + 10
+ call printf (" Status: %2d%% complete\r")
+ call pargi (percent)
+ call flush (STDOUT)
+ }
+ }
+
+ }
+ if (IP_VERBOSE(ip) == YES) {
+ call printf (" Status: Done \n")
+ call flush (STDOUT)
+ }
+end
+
+
+# RAS_READ_RLE - Read a line of RLE encoded data from the file.
+
+procedure ras_read_rle (ras, fd, data, nchars)
+
+pointer ras #i ras struct pointer
+int fd #i file descriptor
+char data[ARB] #u output pixels
+int nchars #i number of pixels to read
+
+int i
+short pix, ras_rdbyte()
+
+long filepos
+common /rascom/ filepos
+
+begin
+ i = 1
+ while (i <= nchars) {
+ if (RAS_COUNT(ras) > 0) {
+ data[i] = RAS_CH(ras)
+ i = i + 1
+ RAS_COUNT(ras) = RAS_COUNT(ras) - 1
+
+ } else {
+ pix = ras_rdbyte (fd)
+ if (pix == RAS_RLE) {
+ RAS_COUNT(ras) = ras_rdbyte (fd)
+ if (RAS_COUNT(ras) == 0) {
+ data[i] = pix
+ i = i + 1
+ } else {
+ RAS_CH(ras) = ras_rdbyte (fd)
+ data[i] = RAS_CH(ras)
+ i = i + 1
+ }
+ } else {
+ data[i] = pix
+ i = i + 1
+ }
+ }
+ }
+end
+
+
+# RAS_RDBYTE - Read a single byte at the current offset from the file.
+
+short procedure ras_rdbyte (fd)
+
+int fd #i file descriptor
+
+short val
+short ip_getb()
+
+long filepos
+common /rascom/ filepos
+
+begin
+ iferr (val = ip_getb (fd, filepos))
+ return (ERR)
+
+ filepos = filepos + 1
+ call ip_lseek (fd, filepos)
+
+ return (val)
+end
diff --git a/pkg/dataio/import/bltins/ipxwd.x b/pkg/dataio/import/bltins/ipxwd.x
new file mode 100644
index 00000000..62a48ff7
--- /dev/null
+++ b/pkg/dataio/import/bltins/ipxwd.x
@@ -0,0 +1,188 @@
+# IPXWD.X - Source file for the IMPORT task X Window Dump builtin format.
+
+include <mach.h>
+include "../import.h"
+
+
+# IP_XWD - Read and process an X Window Dump into an IRAF image.
+
+procedure ip_xwd (ip, fname, info_only, verbose)
+
+pointer ip #i import struct pointer
+char fname[ARB] #i file name
+int info_only #i print out image info only?
+int verbose #i verbosity flag
+
+int fd
+pointer im, cmap
+int nchars
+long depth, cmap_entries, hdr_size
+long hskip, lpad, width,height
+
+long ip_getl()
+
+begin
+ # Get the input file descriptor and initialize the file position.
+ fd = IP_FD(ip)
+ im = IP_IM(ip)
+ call ip_lseek (fd, BOF)
+
+ # Get some information from the header we'll need for processing.
+ hdr_size = ip_getl (fd, 1)
+ width = IP_AXLEN(ip,1)
+ height = IP_AXLEN(ip,2)
+ depth = ip_getl (fd, 45)
+ hskip = IP_HSKIP(ip)
+ lpad = IP_LPAD(ip)
+ cmap_entries = ip_getl (fd, 73)
+ nchars = width + lpad
+
+ # See if we really want to convert this thing.
+ if (info_only == YES) {
+ call ip_xwd_info (ip, fname, depth, cmap_entries, verbose)
+ return
+ }
+
+ # Now process the image. For 24-bit or 32-bit files we have an RGB
+ # image and can process normally, if this is an 8-bit image see if
+ # we have a colormap we need to use.
+
+ if (depth > 8) {
+ call ip_prpix (ip, fd, im, NULL)
+ } else {
+ cmap = NULL
+ if (cmap_entries > 0)
+ call xwd_rdcmap (ip, fd, hdr_size, cmap_entries, cmap)
+ call ip_prband (ip, fd, im, cmap)
+ }
+ IP_CMAP(ip) = NULL
+end
+
+
+# IP_XWD_INFO - Print information about the xwd file.
+
+procedure ip_xwd_info (ip, fname, depth, ncolors, verbose)
+
+pointer ip #i ip struct pointer
+char fname[ARB] #i file name
+int depth #i bits per pixel
+int ncolors #i number of colors
+int verbose #i verbosity flag
+
+begin
+ # If not verbose print a one-liner.
+ if (verbose == NO) {
+ #call printf ("Input file:\n\t")
+ call printf ("%s: %20t%d x %d \t%d-bit X11 Window Dump\n")
+ call pargstr (fname)
+ call pargi (IP_AXLEN(ip,1))
+ call pargi (IP_AXLEN(ip,2))
+ call pargi (depth)
+
+ # Print out the format comment if any.
+ if (IP_COMPTR(ip) != NULL) {
+ if (COMMENT(ip) != '\0') {
+ call printf ("%s\n")
+ call pargstr (COMMENT(ip))
+ }
+ call strcpy ("\0", COMMENT(ip), SZ_LINE)
+ }
+ return
+ }
+
+ # Print a more verbose description.
+ call printf ("%s: %20tX11 Window Dump\n")
+ call pargstr (fname)
+
+ # Print out the format comment if any.
+ if (IP_COMPTR(ip) != NULL) {
+ if (COMMENT(ip) != '\0') {
+ call printf ("%s\n")
+ call pargstr (COMMENT(ip))
+ }
+ call strcpy ("\0", COMMENT(ip), SZ_LINE)
+ }
+
+ call printf ("%20tByte Order:%38t%s\n")
+ if (IP_SWAP(ip) == S_NONE && BYTE_SWAP2 == NO )
+ call pargstr ("Most Significant Byte First")
+ else
+ call pargstr ("Least Significant Byte First")
+
+ call printf ("%20tResolution:%38t%d x %d\n")
+ call pargi (IP_AXLEN(ip,1))
+ call pargi (IP_AXLEN(ip,2))
+
+ call printf ("%20tType: %38t%d-bit %s\n")
+ call pargi (depth)
+ if (ncolors > 0)
+ call pargstr ("Color Index")
+ else
+ call pargstr ("")
+
+ call printf ("%20tHeader size:%38t%d bytes\n")
+ call pargi (IP_HSKIP(ip))
+
+ if (ncolors > 0) {
+ call printf ("%20tColormap:%38t%d entries\n")
+ call pargi (ncolors)
+ } else
+ call printf ("%20tColormap:%38tnone\n")
+
+ call printf ("%20tAlpha Channel: %38t%s\n")
+ if (depth == 32)
+ call pargstr ("8-bit")
+ else
+ call pargstr ("none")
+end
+
+
+# XWD_RDCMAP - Read colormap from an X11 Window Dump file and return a
+# pointer to it.
+
+procedure xwd_rdcmap (ip, fd, hdr_size, ncolors, cmap)
+
+pointer ip #i task struct pointer
+int fd #i file descriptor
+int hdr_size #i header size
+int ncolors #i number of colormap entries
+pointer cmap #i colormap pointer
+
+int i
+long filepos, pixel
+int r, g, b
+char flags, pad
+
+short ip_getb()
+int ip_getu()
+long ip_getl()
+
+define SZ_X11_CSTRUCT 12
+
+begin
+ # Now read the colormap, allocate the pointer if we need to.
+ cmap = NULL
+ if (ncolors == 0)
+ return
+ else
+ call calloc (cmap, CMAP_SIZE*3, TY_CHAR)
+
+ filepos = hdr_size + 3
+ call ip_lseek (fd, filepos)
+ do i = 1, ncolors {
+ pixel = ip_getl (fd, filepos)
+ r = ip_getu (fd, filepos+4)
+ g = ip_getu (fd, filepos+6)
+ b = ip_getu (fd, filepos+8)
+ flags = ip_getb (fd, filepos+10)
+ pad = ip_getb (fd, filepos+11)
+
+ CMAP(cmap,IP_RED,i) = r * 255 / 65535
+ CMAP(cmap,IP_GREEN,i) = g * 255 / 65535
+ CMAP(cmap,IP_BLUE,i) = b * 255 / 65535
+
+ filepos = filepos + SZ_X11_CSTRUCT
+ call ip_lseek (fd, filepos)
+ }
+ IP_CMAP(ip) = cmap
+end
diff --git a/pkg/dataio/import/bltins/mkpkg b/pkg/dataio/import/bltins/mkpkg
new file mode 100644
index 00000000..88c4cadb
--- /dev/null
+++ b/pkg/dataio/import/bltins/mkpkg
@@ -0,0 +1,13 @@
+# Mkpkg file for building the IMPORT task builtin formats.
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+libpkg.a:
+ ipcmap.x ../import.h
+ ipgif.x ../import.h
+ ipras.x ../import.h <mach.h>
+ ipxwd.x ../import.h <mach.h>
+ ;
diff --git a/pkg/dataio/import/fmtdb.x b/pkg/dataio/import/fmtdb.x
new file mode 100644
index 00000000..8e5da296
--- /dev/null
+++ b/pkg/dataio/import/fmtdb.x
@@ -0,0 +1,610 @@
+include <ctotok.h>
+include <evvexpr.h>
+include <fset.h>
+include <error.h>
+include "import.h"
+
+define DEBUG false
+define VDEBUG false
+
+
+.help fmtdb Augl93 "Format Database Interface"
+.ih
+DESCRIPTION
+Format Database Procedures -- Routines for opening the format database given
+in the task parameter, reading sequential and randome records within it, as
+well as getting entried from within a selected record.
+
+PROCEDURES
+.nf
+ PUBLIC PROCEDURES:
+
+ fd = fdb_opendb ()
+ fdb_closedb (fd)
+ fmt = fdb_get_rec (fd, format)
+ fmt = fdb_next_rec (fd)
+ fmt = fdb_scan_records (fd, keyword, getop, opdata, fcn, fcndata)
+ fdbgstr (fmt, param, str, maxchar)
+ fdb_close (fmt)
+
+ PRIVATE PROCEDURES:
+
+ fdb_gfield (fd, fmt, key, val)
+ fdb_gexpr (fd, fmt, expr, maxchars)
+ fdb_strip_colon (in, out, maxch)
+ fdb_strip_quote (in, out, maxch)
+
+.fi
+
+The FDB_OPENDB procedure returns a file descriptor to the database file
+(named in the task parameters), and FDB_CLOSEDB will close the file. When
+searching for a specific format, the FDB_GET_REC procedure will return a
+pointer to a symtab containing the database record. The FDB_NEXT_REC
+will return a symtab pointer to the next record in the database when reading
+it sequentially. The FDB_SCAN_RECS procedure can be used to scan the
+database, returning the symtab pointer to a record whose 'keyword' field eval-
+uates as true. The FDB_CLOSE procedure will free the symtab pointer returned
+by the previous two routines.
+
+Once a pointer is found for a database record the FDBGSTR procedure
+can be used to return a value for an entry within that database record.
+.ih
+SEE ALSO
+Source code
+.endhelp
+
+
+# Symbol table definitions.
+define LEN_INDEX 10 # Length of symtab index
+define LEN_STAB (20*SZ_EXPR) # Length of symtab
+define SZ_SBUF 512 # Size of symtab string buffer
+define SYMLEN SZ_EXPR # Length of symbol structure
+define SZ_FMTVAL SZ_EXPR # Size of format value string
+
+# Symbol table structure
+define FMTVAL Memc[P2C($1)] # Format value string
+
+
+# FDB_OPENDB -- Return a file descriptor to the format database. The
+# specified database may be a list of files in which case they will be
+# concatenated to a single temporary file that is removed when the database
+# is closed.
+
+int procedure fdb_opendb ()
+
+int fd, in, out
+int stat, nfiles
+pointer sp, fname, buf
+pointer dbfiles
+
+int open()
+int clpopni(), clplen(), clgfil()
+
+errchk open, clpopni
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_FNAME, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+
+ dbfiles = clpopni ("database")
+ nfiles = clplen (dbfiles)
+ if (nfiles == 0) {
+ call error (0, "No format database specified.")
+
+ } else if (nfiles == 1) {
+ call clgstr ("database", Memc[fname], SZ_FNAME)
+ stat = clgfil (dbfiles, Memc[fname], SZ_FNAME)
+
+ } else {
+ # The database parameter specified a list, concatenate the files
+ # to a temp file and open that instead.
+ call mktemp ("tmp$db", Memc[fname], SZ_FNAME)
+ out = open (Memc[fname], APPEND, TEXT_FILE)
+ while (clgfil (dbfiles, Memc[buf], SZ_FNAME) != EOF) {
+ in = open (Memc[buf], READ_ONLY, TEXT_FILE)
+ call fcopyo (in, out)
+ call close (in)
+ }
+ call close (out)
+ }
+
+ # Open format database.
+ fd = open (Memc[fname], READ_ONLY, TEXT_FILE)
+
+ call sfree (sp)
+ return (fd)
+end
+
+
+# FDB_CLOSEDB -- Close the format database.
+
+procedure fdb_closedb (fd)
+
+int fd #i file descriptor
+
+pointer sp, buf
+int strncmp()
+
+begin
+ if (fd == NULL)
+ return
+
+ call smark (sp)
+ call salloc (buf, SZ_FNAME, TY_CHAR)
+
+ # Get the database filename, if it's a temp file then the input
+ # was probably and list and we need to clean up.
+ call fstats (fd, F_FILENAME, Memc[buf], SZ_FNAME)
+ call close (fd)
+ if (strncmp (Memc[buf], "tmp$db", 6) == 0)
+ call delete (Memc[buf])
+
+ call sfree (sp)
+end
+
+
+# FDB_GET_REC -- Get the requested format information in symbol table.
+
+pointer procedure fdb_get_rec (fd, format)
+
+int fd #i database file descriptor
+char format[ARB] #i format name
+
+pointer fmt #o format symbol table pointer
+bool found
+char colon
+pointer sp, key, expr, sym
+
+int fscan(), stridx()
+pointer stopen(), stenter()
+bool streq()
+
+errchk stopen, stenter, fscan
+
+begin
+ # Allocate local storage.
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call salloc (expr, SZ_EXPR, TY_CHAR)
+
+ # Find format entry.
+ found = false
+ colon = ':'
+ while (fscan (fd) != EOF) {
+ call fdb_gfield (fd, NULL, Memc[key], Memc[expr])
+ if (stridx (colon, Memc[key]) > 0) {
+ call fdb_strip_colon (Memc[key], Memc[key], SZ_FNAME)
+ } else if (Memc[key]=='#') # skip comment lines
+ next
+ if (streq (Memc[key], format)) {
+ found = true
+ break
+ }
+ }
+ if (!found) { # check if entry was found
+ call sfree (sp)
+ return (NULL)
+ }
+
+ # Create the symbol table.
+ fmt = stopen (format, LEN_INDEX, LEN_STAB, SZ_SBUF)
+
+ # Read the file and enter the parameters in the symbol table.
+ sym = stenter (fmt, "format", SYMLEN)
+ call strcpy (format, FMTVAL(sym), SZ_FMTVAL)
+ while (fscan(fd) != EOF) {
+ call fdb_gfield (fd, fmt, Memc[key], Memc[expr])
+ if (stridx (colon, Memc[key]) > 0) {
+ call fdb_strip_colon (Memc[key], Memc[expr], SZ_FNAME)
+ call strcpy ("alias", Memc[key], SZ_FNAME)
+ } else if (Memc[key] == '#' || Memc[key] == '') {
+ next
+ } else if (Memc[key] == EOS) {
+ call sfree (sp)
+ return (fmt)
+ }
+ sym = stenter (fmt, Memc[key], SYMLEN)
+ call strcpy (Memc[expr], FMTVAL(sym), SZ_FMTVAL)
+ }
+
+ call close (fd)
+ call sfree (sp)
+ return (fmt)
+end
+
+
+# FDB_NEXT_REC -- Open format database and store the requested format
+# information in symbol table.
+
+pointer procedure fdb_next_rec (fd)
+
+int fd #i input binary file descriptor
+
+pointer fmt # Format symbol table pointer
+char colon
+pointer sp, key, expr, sym, tmp
+
+int fscan(), stridx()
+pointer stopen(), stenter()
+
+errchk stopen, stenter, fscan
+
+begin
+ # Allocate local storage.
+ call smark (sp)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call salloc (tmp, SZ_FNAME, TY_CHAR)
+ call salloc (expr, SZ_FMTVAL, TY_CHAR)
+
+ # Skip ahead top the beginning of the next record.
+ colon = ':'
+ while (fscan (fd) != EOF) {
+ Memc[key] = EOS
+ Memc[expr] = EOS
+ call fdb_gfield (fd, NULL, Memc[key], Memc[expr])
+ if (stridx (colon, Memc[key]) > 0) {
+ call fdb_strip_colon (Memc[key], Memc[key], SZ_FNAME)
+ break
+ } else if (Memc[key] != '#' && Memc[key] != EOS) # skip comment
+ next
+
+ }
+
+ # The file will either be position at the BOF or at the end of the
+ # previous record. We will just read until the end of record and
+ # return the pointer.
+
+ # Create symbol table, but strip the ':' first.
+ call fdb_strip_colon (Memc[key], Memc[tmp], SZ_FNAME)
+ fmt = stopen (Memc[tmp], LEN_INDEX, LEN_STAB, SZ_SBUF)
+
+ if (DEBUG) {call eprintf("next_rec: fmt='%s' ");call pargstr(Memc[tmp])}
+
+ # Read the file and enter the parameters in the symbol table.
+ sym = stenter (fmt, "format", SYMLEN)
+ call strcpy (Memc[tmp], FMTVAL(sym), SZ_FMTVAL)
+ while (fscan(fd) != EOF) {
+ call fdb_gfield (fd, fmt, Memc[key], Memc[expr])
+ if (stridx (colon, Memc[key]) > 0) {
+ call fdb_strip_colon (Memc[key], Memc[expr], SZ_FNAME)
+ call strcpy ("alias", Memc[key], SZ_FNAME)
+ } else if (Memc[key] == '#' || Memc[key] == '') {
+ next
+ } else if (Memc[key] == EOS) {
+ call sfree (sp)
+ return (fmt)
+ }
+ sym = stenter (fmt, Memc[key], SYMLEN)
+ call strcpy (Memc[expr], FMTVAL(sym), SZ_FMTVAL)
+ }
+
+ call sfree (sp) # shouldn't get here
+ return (NULL)
+end
+
+
+# FDB_SCAN_RECORDS -- Scan the database for a record whose image_id evaluates
+# as true.
+
+pointer procedure fdb_scan_records (fd, keyword, getop, opdata, fcn, fcndata)
+
+int fd #i input binary file descriptor
+char keyword[ARB] #i keyword to be evaluated
+int getop #i func to get an operand
+int opdata #i data pointer for getop
+int fcn #i user functions in evvexpr
+int fcndata #i data pointer for fcn
+
+pointer sp, expr, fm
+pointer fmt, o
+
+pointer fdb_next_rec(), evvexpr()
+
+errchk evvexpr
+
+begin
+ call smark (sp)
+ call salloc (expr, SZ_EXPR, TY_CHAR)
+ call salloc (fm, SZ_FNAME, TY_CHAR)
+
+ # Rewind the file descriptor.
+ call seek (fd, BOF)
+
+ if (DEBUG) { call eprintf("scan_rec: keyw='%s' ");call pargstr(keyword)}
+
+ # Loop over all of the database records.
+ repeat {
+ fmt = fdb_next_rec (fd)
+ if (fmt == NULL)
+ break
+ call fdbgstr (fmt, keyword, Memc[expr], SZ_EXPR)
+
+ if (DEBUG) {
+ call eprintf(" expr='%s'\n"); call pargstr(Memc[expr])
+ call flush (STDERR)
+ }
+
+ # Evaluate keyword expression.
+ iferr {
+ o = evvexpr (Memc[expr], getop, opdata, fcn, fcndata, EV_RNGCHK)
+ if (O_TYPE(o) != TY_BOOL)
+ call error (0, "Expression must be a boolean")
+
+ } then {
+ call erract (EA_WARN)
+ break
+ }
+
+ if (O_VALI(o) == YES) { # see if we've found it
+ if (DEBUG) {
+ call fdbgstr (fmt, "format", Memc[fm], SZ_FNAME)
+ call eprintf(" format='%s'\n");call pargstr(Memc[fm])
+ }
+ call evvfree (o)
+ call sfree (sp)
+ return (fmt)
+ }
+
+ call evvfree (o)
+ call fdb_close (fmt) # free fmt pointer
+ }
+
+ call sfree (sp)
+ return (NULL)
+end
+
+
+# FDBCLOSE -- Close the format symbol table pointer.
+
+procedure fdb_close (fmt)
+
+pointer fmt #i Format symbol table pointer
+
+begin
+ if (fmt != NULL)
+ call stclose (fmt)
+end
+
+
+# FDBGSTR -- Get string valued format parameter. We simply return the
+# expression, evaluation is up to the caller.
+
+procedure fdbgstr (fmt, param, str, maxchar)
+
+pointer fmt #i format symbol table pointer
+char param[ARB] #i format parameter
+char str[ARB] #o format parameter value
+int maxchar #i maximum characters for string
+
+pointer sym, stfind()
+
+begin
+ call aclrc (str, maxchar)
+ sym = stfind (fmt, param)
+ if (sym == NULL)
+ call strcpy ("", str, maxchar)
+ else
+ call strcpy (FMTVAL(sym), str, maxchar)
+end
+
+
+## END OF PUBLIC PROCEDURES ##
+
+
+# FDB_GFIELD - Get field in the database record.
+
+procedure fdb_gfield (fd, fmt, keyword, expr)
+
+int fd #i file descriptor
+pointer fmt #i format symtab pointer
+char keyword[ARB] #o field keyword
+char expr[ARB] #o field expression
+
+pointer sp, tmp
+
+begin
+ call smark (sp)
+ call salloc (tmp, SZ_FNAME, TY_CHAR)
+
+ call gargwrd (keyword, SZ_FNAME)
+ call gargwrd (Memc[tmp], SZ_FNAME)
+
+ if (keyword[1] == EOS) {
+ call sfree (sp)
+ return
+ #} else if (Memc[tmp] == '#') {
+ } else if (keyword[1] == '#') {
+ expr[1] = EOS
+ } else if (Memc[tmp] != EOS)
+ call fdb_gexpr (fd, fmt, expr, SZ_EXPR)
+ else
+ expr[1] = EOS
+
+ if (VDEBUG && keyword[1] != '#' && keyword[1] != '') {
+ call eprintf("'%s'='%s'\n")
+ call pargstr (keyword) ; call pargstr (expr)
+ }
+
+ call sfree (sp)
+end
+
+
+# FDB_GEXPR - Get an expression from the input stream.
+
+procedure fdb_gexpr (fd, fmt, expr, maxchars)
+
+int fd #i file descriptor
+pointer fmt #i format symtab pointer
+char expr[ARB] #o returned expression
+int maxchars #i maxchars
+
+pointer sp, ntok, tok, tokval, next_tok, last_tok
+pointer sym
+int level, qlevel
+
+int fscan()
+pointer stfind()
+
+define dopar_ 99
+
+begin
+ call smark (sp)
+ call salloc (tok, SZ_FNAME, TY_CHAR)
+ call salloc (ntok, SZ_FNAME, TY_CHAR)
+
+ # Gather the expression. For now we'll just eat everything up until
+ # the closing parenthesis.
+ call aclrc (expr, maxchars)
+
+ # An expression is made up of a numeric or symbolic constant, a
+ # quoted literal string, or some boolean or arithmetic operation.
+ # The strategy is to get the first token and take action depending
+ # on it's value and whether a following token completes the expr-
+ # ession. Expressions may break across newlines, literal strings
+ # must be enclosed in double quotes.
+
+ level = 0
+ qlevel = 0
+ last_tok = TOK_UNKNOWN
+ repeat {
+ call gargtok (tokval, Memc[tok], SZ_EXPR)
+
+ switch (tokval) {
+ case TOK_NUMBER:
+ call strcat (Memc[tok], expr, SZ_EXPR)
+ case TOK_STRING:
+ # There are no operations on strings, but they might be passed
+ # to a function as an argument, so check the level. Oh yeah,
+ # keep the double quotes in the string.
+ call strcat ("\"", expr, SZ_EXPR)
+ call strcat (Memc[tok], expr, SZ_EXPR)
+ call strcat ("\"", expr, SZ_EXPR)
+ case TOK_PUNCTUATION:
+ if (Memc[tok] == '(')
+ level = level + 1
+ else if (Memc[tok] == ')')
+ level = level - 1
+ call strcat (Memc[tok], expr, SZ_EXPR)
+ case TOK_OPERATOR:
+ if (Memc[tok] == '"') { # pass quoted strings
+ if (qlevel == 1)
+ qlevel = 0
+ else if (qlevel == 0)
+ qlevel = 1
+ }
+ if (Memc[tok] == '#' && qlevel == 0) { # skip comments
+ if (fscan (fd) == EOF)
+ call eprintf ("WARNING: Unexpected EOF\n")
+ if (level == 0 && last_tok != TOK_OPERATOR)
+ break
+ } else
+ call strcat (Memc[tok], expr, SZ_EXPR)
+ case TOK_NEWLINE:
+ if (level != 0 || last_tok == TOK_OPERATOR) {
+ if (fscan (fd) == EOF)
+ call eprintf ("WARNING: Unexpected EOF\n")
+ }
+ case TOK_IDENTIFIER:
+ if (Memc[tok] == '$') {
+ call strcat (Memc[tok], expr, SZ_EXPR)
+ } else if (fmt != NULL) {
+ sym = stfind (fmt, Memc[tok])
+ if (sym == NULL) {
+ if (Memc[tok] == 'F') {
+ call strcat (Memc[tok], expr, SZ_EXPR)
+ } else {
+ call gargtok (next_tok, Memc[ntok], SZ_EXPR)
+ if (Memc[ntok] == '(') {
+ # Copy to output buffer, it's a function name.
+ call strcat (Memc[tok], expr, SZ_EXPR)
+ call strcat (Memc[ntok], expr, SZ_EXPR)
+ tokval = next_tok
+ level = level + 1
+ next
+ } else {
+ # It's an undefined database field.
+ call eprintf("Undefined database field '%s'.\n")
+ call pargstr (Memc[tok])
+ }
+ }
+ } else
+ call strcat (FMTVAL(sym), expr, SZ_EXPR)
+ } else {
+ call strcat (Memc[tok], expr, SZ_EXPR)
+ }
+ call gargtok (next_tok, Memc[tok], SZ_EXPR)
+dopar_ if (Memc[tok] == '(')
+ level = level + 1
+ else if (Memc[tok] == ')') {
+ level = level - 1
+ if (level == 0) {
+ call strcat (Memc[tok], expr, SZ_EXPR)
+ break
+ }
+ }
+ if (next_tok != TOK_NEWLINE)
+ call strcat (Memc[tok], expr, SZ_EXPR)
+ tokval = next_tok
+ default:
+ break
+ }
+
+ last_tok = tokval
+ }
+
+ # Check for an obvious error.
+ if (level > 0)
+ call eprintf ("Missing right paren in expression: '%s'\n")
+ else if (level < 0)
+ call eprintf ("Missing left paren in expression: '%s'\n")
+ call pargstr (expr)
+
+ call sfree (sp)
+end
+
+
+# FDB_STRIP_COLON -- Return the input string up to a ':' character.
+
+procedure fdb_strip_colon (in, out, maxch)
+
+char in[ARB] #i input string
+char out[ARB] #o output string
+int maxch #i max chars out
+
+int ip, op
+
+begin
+ op = 1
+ do ip = 1, ARB {
+ if (in[ip] == ':' || op > maxch || in[ip] == EOS)
+ break
+ out[op] = in[ip]
+ op = op + 1
+ }
+ out[op] = EOS
+end
+
+
+# FDB_STRIP_QUOTE -- Strip double quote chars from the string.
+
+procedure fdb_strip_quote (in, out, maxch)
+
+char in[ARB] #i input string
+char out[ARB] #o output string
+int maxch #i max chars out
+
+int ip, op
+
+begin
+ op = 1
+ do ip = 1, ARB {
+ if (op > maxch || in[ip] == EOS)
+ break
+ if (in[ip] != '"') {
+ out[op] = in[ip]
+ op = op + 1
+ }
+ }
+ out[op] = EOS
+end
diff --git a/pkg/dataio/import/generic/ipdb.x b/pkg/dataio/import/generic/ipdb.x
new file mode 100644
index 00000000..4dfb81c7
--- /dev/null
+++ b/pkg/dataio/import/generic/ipdb.x
@@ -0,0 +1,813 @@
+include <evvexpr.h>
+include <error.h>
+include <mach.h>
+include <imhdr.h>
+include "../import.h"
+include "../ipfcn.h"
+
+define DEBUG false
+
+
+# IP_EVAL_DBREC -- For each of the keywords defined in the database record,
+# evaluate the expression and load the task structure.
+
+procedure ip_eval_dbrec (ip)
+
+pointer ip #i task struct pointer
+
+int ival
+pointer sp, dims, pixtype, err
+pointer np, stp, sym
+
+pointer stname(), sthead(), stnext
+int or(), ip_dbgeti()
+bool streq()
+
+errchk ip_dbgeti()
+
+begin
+ call smark (sp)
+ call salloc (dims, SZ_EXPR, TY_CHAR)
+ call salloc (pixtype, SZ_EXPR, TY_CHAR)
+ call salloc (err, SZ_EXPR, TY_CHAR)
+ call aclrc (Memc[dims], SZ_EXPR)
+ call aclrc (Memc[pixtype], SZ_EXPR)
+ call aclrc (Memc[err], SZ_EXPR)
+
+ # Load the defaults.
+ call ip_load_defaults (ip)
+
+ # First thing we do is get the byte swap flag so the remaining
+ # fields will be interpreted correctly.
+ ifnoerr (ival = ip_dbgeti (ip, "bswap"))
+ IP_SWAP(ip) = ival
+
+ # Next, we handle 'interleave', 'dims' and 'pixtype' as a special case
+ # since for band- and line-interleaved files we may need to fix up the
+ # pixtype pointers.
+ ifnoerr (ival = ip_dbgeti (ip, "interleave"))
+ IP_INTERLEAVE(ip) = ival
+
+ ifnoerr (call ip_dbstr (ip, "dims", Memc[dims], SZ_EXPR))
+ call ip_do_dims (ip, Memc[dims])
+
+ ifnoerr (call ip_dbstr (ip, "pixtype", Memc[pixtype], SZ_EXPR)) {
+ if (Memc[pixtype] == '"')
+ call fdb_strip_quote (Memc[pixtype], Memc[pixtype], SZ_EXPR)
+ call ip_do_pixtype (ip, Memc[pixtype])
+ }
+
+ # Loop over every symbol in the table.
+ stp = IP_FSYM(ip)
+ for (sym=sthead(stp); sym != NULL; sym=stnext(stp,sym)) {
+ np = stname (stp, sym)
+
+ if (streq(Memc[np],"format") || # ignored or found already
+ streq(Memc[np],"alias") ||
+ streq(Memc[np],"image_id") ||
+ streq(Memc[np],"interleave") ||
+ streq(Memc[np],"dims") ||
+ streq(Memc[np],"pixtype") ||
+ streq(Memc[np],"id_string") ||
+ streq(Memc[np],"bswap")) {
+ next
+ } else if (streq(Memc[np],"hskip")) {
+ IP_HSKIP(ip) = ip_dbgeti (ip, "hskip")
+ } else if (streq(Memc[np],"tskip")) {
+ IP_TSKIP(ip) = ip_dbgeti (ip, "tskip")
+ } else if (streq(Memc[np],"bskip")) {
+ IP_BSKIP(ip) = ip_dbgeti (ip, "bskip")
+ } else if (streq(Memc[np],"lskip")) {
+ IP_LSKIP(ip) = ip_dbgeti (ip, "lskip")
+ } else if (streq(Memc[np],"lpad")) {
+ IP_LPAD(ip) = ip_dbgeti (ip, "lpad")
+ } else if (streq(Memc[np],"yflip")) {
+ if (ip_dbgeti (ip, "yflip") == YES)
+ IP_FLIP(ip) = or (IP_FLIP(ip), FLIP_Y)
+ } else if (streq(Memc[np],"error")) {
+ if (IP_OUTPUT(ip) != IP_INFO)
+ call ip_do_error (ip, Memc[P2C(sym)])
+ } else if (streq(Memc[np],"comment")) {
+ call fdb_strip_quote (Memc[P2C(sym)], Memc[P2C(sym)], SZ_LINE)
+ call ip_do_comment (ip, Memc[P2C(sym)])
+ } else {
+ call eprintf ("Warning: Unknown database keyword '%s'.\n")
+ call pargstr (Memc[np])
+ }
+ }
+
+ if (DEBUG) { call zzi_prstruct ("eval dbrec:", ip) }
+ call sfree (sp)
+end
+
+
+# IP_LOAD_DEFAULTS -- Load the default input parameters to the task structure.
+
+procedure ip_load_defaults (ip)
+
+pointer ip #i task struct pointer
+
+begin
+ IP_SWAP(ip) = DEF_SWAP # type of byte swapping
+ IP_INTERLEAVE(ip) = DEF_INTERLEAVE # type of data interleaving
+ IP_HSKIP(ip) = DEF_HSKIP # bytes to skip before data
+ IP_TSKIP(ip) = DEF_TSKIP # bytes to skip after data
+ IP_BSKIP(ip) = DEF_BSKIP # bytes between image bands
+ IP_LSKIP(ip) = DEF_LSKIP # bytes to skip at front of
+ IP_LPAD(ip) = DEF_LPAD # bytes to skip at end of
+
+ # zero image dimensions
+ for (IP_NDIM(ip)=IM_MAXDIM; IP_NDIM(ip) > 0; IP_NDIM(ip)=IP_NDIM(ip)-1)
+ IP_AXLEN(ip,IP_NDIM(ip)) = 0
+end
+
+
+# IP_DBFCN -- Called by evvexpr to execute format database special functions.
+
+procedure ip_dbfcn (ip, fcn, args, nargs, o)
+
+pointer ip #i task struct pointer
+char fcn[ARB] #i function to be executed
+pointer args[ARB] #i argument list
+int nargs #i number of arguments
+pointer o #o operand pointer
+
+pointer sp, buf, outstr
+int fd, func, v_nargs
+int i, len, nchar, ival, cur_offset, swap
+char ch
+short sval
+real rval
+double dval
+
+short ip_getb(), ip_gets()
+int strdic(), ip_line(), ip_locate(), ip_getu()
+int ctoi(), ctol(), ctor(), ctod(), ctocc(), ctowrd()
+int and(), strlen(), clgeti()
+long ip_getl()
+real ip_getr(), ip_getn()
+double ip_getd(), ip_getn8()
+bool strne(), streq()
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call aclrc (Memc[buf], SZ_LINE)
+ call aclrc (Memc[outstr], SZ_LINE)
+
+ # Lookup function in dictionary.
+ func = strdic (fcn, Memc[buf], SZ_LINE, DB_FUNCTIONS)
+ if (func > 0 && strne(fcn,Memc[buf]))
+ func = 0
+
+ # Abort if the function is not known.
+ if (func <= 0)
+ call xev_error1 ("unknown function `%s' called", fcn)
+
+
+ # Verify the correct number of arguments, negative value means a
+ # variable number of args, handle it in the evaluation.
+ switch (func) {
+ case CTOCC, CTOD, CTOI, CTOL, CTOR, CTOWRD:
+ v_nargs = -1
+
+ case GETSTR:
+ v_nargs = -1
+ case GETB, GETU, GETI, GETI2, GETI4, GETR, GETR4, GETR8,
+ GETN, GETN4, GETN8:
+ v_nargs = 1
+
+ case LOCATE:
+ v_nargs = -1
+ case LINE, SKIP:
+ v_nargs = 1
+
+ case BSWAP:
+ v_nargs = 1
+ case PARAMETER, DEFAULT:
+ v_nargs = 1
+ case SUBSTR:
+ v_nargs = 3
+ case STRIDX:
+ v_nargs = 2
+ case LSB_HOST, MSB_HOST:
+ v_nargs = 0
+ }
+ if (v_nargs > 0 && nargs != v_nargs)
+ call xev_error2 ("function `%s' requires %d arguments",
+ fcn, v_nargs)
+ else if (v_nargs < 0 && nargs < abs(v_nargs))
+ call xev_error2 ("function `%s' requires at least %d arguments",
+ fcn, abs(v_nargs))
+
+ fd = IP_FD(ip)
+ swap = IP_SWAP(ip)
+ cur_offset = IP_OFFSET(ip)
+
+ if (DEBUG) {
+ call eprintf ("cur_offset=%d nargs=%d func=%s swap=%d\n")
+ call pargi(cur_offset) ; call pargi(nargs)
+ call pargstr(fcn) ; call pargi (swap)
+ do i = 1, nargs
+ call zzi_pevop (args[i])
+ call eprintf ("init op => ") ; call zzi_pevop(o)
+
+ }
+
+ # Evaluate the function.
+ switch (func) {
+ case CTOCC: # run the fmtio equivalents of the argument
+ if (nargs == 1)
+ ch = ip_getb (fd, O_VALI(args[1]))
+ else
+ ch = ip_getb (fd, cur_offset)
+ len = ctocc (ch, Memc[outstr], SZ_FNAME) + 1
+ call ip_initop (o, len, TY_CHAR)
+ call aclrc (O_VALC(o), len)
+ call amovc (Memc[outstr], O_VALC(o), len)
+ cur_offset = cur_offset + 1
+ call ip_lseek (fd, cur_offset)
+
+ case CTOWRD:
+ if (nargs == 1)
+ call ip_gstr (fd, O_VALI(args[1]), SZ_FNAME, Memc[outstr])
+ else
+ call ip_gstr (fd, cur_offset, SZ_FNAME, Memc[outstr])
+ nchar = ctowrd (Memc[outstr], i, Memc[outstr], SZ_FNAME) + 1
+ call ip_initop (o, nchar, TY_CHAR)
+ call aclrc (O_VALC(o), nchar)
+ call amovc (Memc[outstr], O_VALC(o), nchar)
+ cur_offset = cur_offset + nchar + 1
+ call ip_lseek (fd, cur_offset)
+
+ case CTOI:
+ i = 1
+ if (nargs == 1) {
+ call ip_gstr (fd, O_VALI(args[i]), SZ_FNAME, Memc[outstr])
+ nchar = ctoi (Memc[outstr], i, ival)
+ cur_offset = cur_offset + nchar - 1
+ } else if (nargs == 2) {
+ call ip_gstr (fd, O_VALI(args[1]), O_VALI(args[2]),Memc[outstr])
+ nchar = ctoi (Memc[outstr], i, ival)
+ cur_offset = O_VALI(args[1]) + nchar - 1
+ }
+ call ip_lseek (fd, cur_offset)
+ O_TYPE(o) = TY_INT
+
+ case CTOL:
+ i = 1
+ if (nargs == 1) {
+ call ip_gstr (fd, O_VALI(args[i]), SZ_FNAME, Memc[outstr])
+ nchar = ctol (Memc[outstr], i, ival)
+ cur_offset = cur_offset + nchar - 1
+ } else if (nargs == 2) {
+ call ip_gstr (fd, O_VALI(args[1]), O_VALI(args[2]),Memc[outstr])
+ nchar = ctol (Memc[outstr], i, ival)
+ cur_offset = O_VALI(args[1]) + nchar - 1
+ }
+ call ip_lseek (fd, cur_offset)
+ O_TYPE(o) = TY_LONG
+
+ case CTOR:
+ i = 1
+ if (nargs == 1) {
+ call ip_gstr (fd, O_VALI(args[i]), SZ_FNAME, Memc[outstr])
+ nchar = ctor (Memc[outstr], i, rval)
+ cur_offset = cur_offset + nchar - 1
+ } else if (nargs == 2) {
+ call ip_gstr (fd, O_VALI(args[1]), O_VALI(args[2]),Memc[outstr])
+ nchar = ctor (Memc[outstr], i, rval)
+ cur_offset = O_VALI(args[1]) + nchar - 1
+ }
+ call ip_lseek (fd, cur_offset)
+ O_TYPE(o) = TY_REAL
+
+ case CTOD:
+ i = 1
+ if (nargs == 1) {
+ call ip_gstr (fd, O_VALI(args[i]), SZ_FNAME, Memc[outstr])
+ nchar = ctod (Memc[outstr], i, dval)
+ cur_offset = cur_offset + nchar - 1
+ } else if (nargs == 2) {
+ call ip_gstr (fd, O_VALI(args[1]), O_VALI(args[2]),Memc[outstr])
+ nchar = ctod (Memc[outstr], i, dval)
+ cur_offset = O_VALI(args[1]) + nchar - 1
+ }
+ call ip_lseek (fd, cur_offset)
+ O_TYPE(o) = TY_DOUBLE
+
+ case GETSTR:
+ if (nargs == 1) {
+ call ip_gstr (fd, cur_offset, O_VALI(args[1]), Memc[outstr])
+ cur_offset = cur_offset + O_VALI(args[1])
+ } else if (nargs == 2) {
+ call ip_gstr (fd, O_VALI(args[1]), O_VALI(args[2]),Memc[outstr])
+ cur_offset = O_VALI(args[1]) + O_VALI(args[2]) - 1
+ }
+ if (strlen(Memc[outstr]) == 0) {
+ len = strlen ("ERR") + 1
+ call ip_initop (o, len, TY_CHAR)
+ call aclrc (O_VALC(o), len)
+ call strcpy ("ERR", O_VALC(o), len-1)
+ } else {
+ len = strlen (Memc[outstr]) + 1
+ call ip_initop (o, len, TY_CHAR)
+ call aclrc (O_VALC(o), len)
+ call amovc (Memc[outstr], O_VALC(o), len-1)
+ }
+
+ case GETB:
+ if (nargs == 0) {
+ sval = ip_getb (fd, cur_offset)
+ cur_offset = cur_offset + SZB_CHAR
+ } else {
+ sval = ip_getb (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + SZB_CHAR
+ }
+ ival = sval
+ O_TYPE(o) = TY_INT
+
+ case GETU:
+ if (nargs == 0) {
+ sval = short (ip_getu (fd, cur_offset))
+ cur_offset = cur_offset + (SZB_CHAR * SZ_SHORT)
+ } else {
+ sval = short (ip_getu (fd, O_VALI(args[1])))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_SHORT)
+ }
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2)
+ call bswap2 (sval, 1, sval, 1, (SZ_SHORT*SZB_CHAR))
+ ival = sval
+ O_TYPE(o) = TY_INT
+
+ case GETI, GETI2:
+ if (nargs == 0) {
+ sval = ip_gets (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_SHORT)
+ } else {
+ sval = ip_gets (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_SHORT)
+ }
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2)
+ call bswap2 (sval, 1, sval, 1, (SZ_SHORT*SZB_CHAR))
+ ival = sval
+ O_TYPE(o) = TY_INT
+
+ case GETI4:
+ if (nargs == 0) {
+ ival = ip_getl (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_LONG)
+ } else {
+ ival = ip_getl (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_LONG)
+ }
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I4)
+ call bswap4 (ival, 1, ival, 1, (SZ_INT32*SZB_CHAR))
+ O_TYPE(o) = TY_INT
+
+ case GETR, GETR4:
+ if (nargs == 0) {
+ rval = ip_getr (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_REAL)
+ } else {
+ rval = ip_getr (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_REAL)
+ }
+ if (and(swap, S_ALL) == S_ALL) # handle byte-swapping
+ call bswap4 (rval, 1, rval, 1, (SZ_REAL*SZB_CHAR))
+ O_TYPE(o) = TY_REAL
+
+ case GETR8:
+ if (nargs == 0) {
+ dval = ip_getd (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_DOUBLE)
+ } else {
+ dval = ip_getd (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_DOUBLE)
+ }
+ if (and(swap, S_ALL) == S_ALL) # handle byte-swapping
+ call bswap8 (dval, 1, dval, 1, (SZ_DOUBLE*SZB_CHAR))
+ O_TYPE(o) = TY_DOUBLE
+
+ case GETN, GETN4:
+ if (nargs == 0) {
+ rval = ip_getn (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_REAL)
+ } else {
+ rval = ip_getn (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_REAL)
+ }
+ if (and(swap, S_ALL) == S_ALL) # handle byte-swapping
+ call bswap4 (rval, 1, rval, 1, (SZ_REAL*SZB_CHAR))
+ O_TYPE(o) = TY_REAL
+
+ case GETN8:
+ if (nargs == 0) {
+ dval = ip_getn8 (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_DOUBLE)
+ } else {
+ dval = ip_getn8 (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_DOUBLE)
+ }
+ if (and(swap, S_ALL) == S_ALL) # handle byte-swapping
+ call bswap8 (dval, 1, dval, 1, (SZ_DOUBLE*SZB_CHAR))
+ O_TYPE(o) = TY_DOUBLE
+
+ case LOCATE: # locate the pattern in the file
+ if (nargs == 1)
+ ival = ip_locate (fd, cur_offset, O_VALC(args[1]))
+ else if (nargs == 2)
+ ival = ip_locate (fd, O_VALI(args[1]), O_VALC(args[2]))
+ if (ival == ERR)
+ ival = 1
+ O_TYPE(o) = TY_INT
+ cur_offset = ival
+
+ case LINE: # locate the line no. in the file
+ ival = ip_line (fd, O_VALI(args[1]))
+ if (ival == ERR)
+ ival = 1
+ O_TYPE(o) = TY_INT
+ cur_offset = ival
+
+ case SKIP: # skip a certain number of bytes
+ ival = O_VALI(args[1])
+ O_TYPE(o) = TY_INT
+ cur_offset = cur_offset + ival
+
+ case BSWAP: # byte-swap argument
+ O_TYPE(o) = O_TYPE(args[1])
+ switch (O_TYPE(args[1])) {
+ case TY_SHORT:
+ call bswap2 (O_VALS(args[1]), 1, sval, 1, (SZ_SHORT*SZB_CHAR))
+ case TY_INT:
+ call bswap4 (O_VALI(args[1]), 1, ival, 1, (SZ_INT32*SZB_CHAR))
+ case TY_LONG:
+ call bswap4 (O_VALL(args[1]), 1, ival, 1, (SZ_LONG*SZB_CHAR))
+ case TY_REAL:
+ call bswap4 (O_VALR(args[1]), 1, rval, 1, (SZ_REAL*SZB_CHAR))
+ case TY_DOUBLE:
+ call bswap8 (O_VALD(args[1]), 1, dval, 1, (SZ_DOUBLE*SZB_CHAR))
+ }
+
+ case PARAMETER: # return current task parameter value
+ if (streq(O_VALC(args[1]),"dims")) {
+ call clgstr ("dims", Memc[outstr], SZ_FNAME)
+ len = strlen (Memc[outstr]) + 1
+ call ip_initop (o, len, TY_CHAR)
+ call strcpy (Memc[outstr], O_VALC(o), len)
+ } else if (streq(O_VALC(args[1]),"pixtype")) {
+ call clgstr ("pixtype", Memc[outstr], SZ_FNAME)
+ len = strlen (Memc[outstr]) + 1
+ call ip_initop (o, len, TY_CHAR)
+ call strcpy (Memc[outstr], O_VALC(o), len)
+ } else if (streq(O_VALC(args[1]),"interleave")) {
+ ival = clgeti ("interleave")
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"bswap")) {
+ call clgstr ("bswap", Memc[outstr], SZ_FNAME)
+ if (strne("no",Memc[outstr]) && strne("none",Memc[outstr]))
+ ival = YES
+ else
+ ival = NO
+ O_TYPE(o) = TY_BOOL
+ } else if (streq(O_VALC(args[1]),"hskip")) {
+ ival = clgeti ("hskip")
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"tskip")) {
+ ival = clgeti ("tskip")
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"bskip")) {
+ ival = clgeti ("bskip")
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"lskip")) {
+ ival = clgeti ("lskip")
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"lpad")) {
+ ival = clgeti ("lpad")
+ O_TYPE(o) = TY_INT
+ }
+
+ case DEFAULT: # return default task parameter value
+ if (streq(O_VALC(args[1]),"dims")) {
+ call ip_initop (o, 1, TY_CHAR)
+ call strcpy ("", O_VALC(o), 1)
+ } else if (streq(O_VALC(args[1]),"pixtype")) {
+ call ip_initop (o, 1, TY_CHAR)
+ call strcpy ("", O_VALC(o), 1)
+ } else if (streq(O_VALC(args[1]),"interleave")) {
+ ival = DEF_INTERLEAVE
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"bswap")) {
+ ival = DEF_SWAP
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"hskip")) {
+ ival = DEF_HSKIP
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"tskip")) {
+ ival = DEF_TSKIP
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"bskip")) {
+ ival = DEF_BSKIP
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"lskip")) {
+ ival = DEF_LSKIP
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"lpad")) {
+ ival = DEF_LPAD
+ O_TYPE(o) = TY_INT
+ }
+
+ case LSB_HOST: # host is an LSB byte ordered machine
+ if (BYTE_SWAP2 == YES)
+ ival = YES
+ else
+ ival = NO
+ O_TYPE(o) = TY_BOOL
+
+ case MSB_HOST: # host is an MSB byte ordered machine
+ if (BYTE_SWAP2 == NO)
+ ival = YES
+ else
+ ival = NO
+ O_TYPE(o) = TY_BOOL
+
+ case SUBSTR: # return a substring of the argument
+
+ case STRIDX: # return offset of a char w/in str
+
+ }
+
+ # Write result to output operand.
+ O_LEN(o) = 0
+ switch (O_TYPE(o)) {
+ case TY_USHORT, TY_SHORT:
+ O_VALS(o) = sval
+ case TY_INT, TY_BOOL:
+ O_VALI(o) = ival
+ case TY_LONG:
+ O_VALL(o) = ival
+ case TY_REAL:
+ O_VALR(o) = rval
+ case TY_DOUBLE:
+ O_VALD(o) = dval
+ }
+
+ if (DEBUG) { call eprintf("ip_dbfcn: ") ; call zzi_pevop (o) }
+
+ IP_OFFSET(ip) = cur_offset
+ call sfree (sp)
+end
+
+
+# IP_DBSTR -- Get a string valued expression from the database.
+
+procedure ip_dbstr (ip, param, outstr, maxch)
+
+pointer ip #i task struct pointer
+char param[ARB] #i parameter to evaluate
+char outstr[ARB] #o result string
+int maxch #i max length of string
+
+pointer sp, expr, o
+
+int locpr(), strlen()
+pointer evvexpr()
+extern ip_getop(), ip_dbfcn()
+errchk evvexpr
+
+begin
+ call smark (sp)
+ call salloc (expr, SZ_EXPR, TY_CHAR)
+ call aclrc (Memc[expr], SZ_EXPR)
+
+ # Get the requested parameter.
+ call aclrc (outstr, SZ_EXPR)
+ call fdbgstr (IP_FSYM(ip), param, Memc[expr], SZ_EXPR)
+ if (Memc[expr] == EOS)
+ call error (1, "FDBGET: Format parameter not found")
+
+ if (DEBUG) {
+ call eprintf("ip_dbstr: expr='%s' len=%d ");call pargstr(Memc[expr])
+ call pargi(strlen(Memc[expr]))
+ }
+
+ # Evaluate the expression.
+ iferr {
+ o = evvexpr (Memc[expr], locpr(ip_getop), ip,
+ locpr(ip_dbfcn), ip, EV_RNGCHK)
+ if (O_TYPE(o) != TY_CHAR)
+ call error (0, "ip_dbstr: Expression must be a string valued")
+ else
+ call amovc (O_VALC(o), outstr, (min(strlen(O_VALC(o)),maxch)))
+ } then
+ call erract (EA_WARN)
+
+ if (DEBUG) { call eprintf ("outstr=:%s:\n") ; call pargstr (outstr) }
+
+ call evvfree (o)
+ call sfree (sp)
+end
+
+
+
+# IP_DBGETI -- Get integer valued format parameter from the database.
+
+int procedure ip_dbgeti (ip, param)
+
+pointer ip #i task struct pointer
+char param[ARB] #i requested parameter
+
+int val
+pointer sp, expr, o
+
+int locpr()
+pointer evvexpr()
+extern ip_getop(), ip_dbfcn()
+errchk evvexpr
+
+begin
+ call smark (sp)
+ call salloc (expr, SZ_EXPR, TY_CHAR)
+
+ # Get the requested parameter.
+ call fdbgstr (IP_FSYM(ip), param, Memc[expr], SZ_EXPR)
+ if (Memc[expr] == EOS)
+ call error (1, "IP_DBGET: Format parameter not found")
+
+ # Evaluate the expression.
+ if (DEBUG) {
+ call eprintf ("ip_dbget: expr='%s'\n")
+ call pargstr (Memc[expr])
+ call flush (STDERR)
+ }
+ iferr {
+ o = evvexpr (Memc[expr], locpr(ip_getop), ip,
+ locpr(ip_dbfcn), ip, EV_RNGCHK)
+ if (O_TYPE(o) == TY_BOOL) {
+ val = O_VALI(o)
+ } else if (O_TYPE(o) != TY_INT && O_TYPE(o) != TY_SHORT) {
+ call error (0, "Expression must be an integer")
+ } else
+ val = O_VALI(o)
+
+ if (DEBUG) {
+ call eprintf ("ip_dbget: val=%d type=%d ecpr=:%s:\n")
+ call pargi (val)
+ call pargi (O_TYPE(o))
+ call pargstr (Memc[expr])
+ call flush (STDERR)
+ }
+ } then
+ call erract (EA_WARN)
+
+ call evvfree (o)
+ call sfree (sp)
+ return (val)
+end
+
+
+# IP_DBGETR -- Get real valued format parameter from the database.
+
+real procedure ip_dbgetr (ip, param)
+
+pointer ip #i task struct pointer
+char param[ARB] #i requested parameter
+
+real val
+pointer sp, expr, o
+
+int locpr()
+pointer evvexpr()
+extern ip_getop(), ip_dbfcn()
+errchk evvexpr
+
+begin
+ call smark (sp)
+ call salloc (expr, SZ_EXPR, TY_CHAR)
+
+ # Get the requested parameter.
+ call fdbgstr (IP_FSYM(ip), param, Memc[expr], SZ_EXPR)
+ if (Memc[expr] == EOS)
+ call error (1, "IP_DBGET: Format parameter not found")
+
+ # Evaluate the expression.
+ if (DEBUG) {
+ call eprintf ("ip_dbget: expr='%s'\n")
+ call pargstr (Memc[expr])
+ call flush (STDERR)
+ }
+ iferr {
+ o = evvexpr (Memc[expr], locpr(ip_getop), ip,
+ locpr(ip_dbfcn), ip, EV_RNGCHK)
+ if (O_TYPE(o) == TY_BOOL) {
+ val = O_VALI(o)
+ } else if (O_TYPE(o) != TY_REAL) {
+ call error (0, "Expression must be a real")
+ } else
+ val = O_VALR(o)
+
+ if (DEBUG) {
+ call eprintf ("ip_dbget: val=%d type=%d ecpr=:%s:\n")
+ call pargr (val)
+ call pargi (O_TYPE(o))
+ call pargstr (Memc[expr])
+ call flush (STDERR)
+ }
+ } then
+ call erract (EA_WARN)
+
+ call evvfree (o)
+ call sfree (sp)
+ return (val)
+end
+
+
+# IP_DO_ERROR -- Process the error parameter.
+
+procedure ip_do_error (ip, expr)
+
+pointer ip #i task struct pointer
+char expr[ARB] #i error string
+
+pointer o
+
+int locpr()
+pointer evvexpr()
+extern ip_getop(), ip_dbfcn()
+bool strne()
+errchk evvexpr
+
+begin
+ if (DEBUG) {call eprintf ("error expr: '%s' ") ; call pargstr (expr)}
+
+ # Evaluate the expression.
+ iferr {
+ o = evvexpr (expr, locpr(ip_getop), ip, locpr(ip_dbfcn), ip,
+ EV_RNGCHK)
+
+ if (DEBUG) { call eprintf("-> '%s'\n") ; call pargstr(O_VALC(o)) }
+
+ if (O_TYPE(o) != TY_CHAR)
+ call error (2, "do_error: Expression must be a string valued")
+ else {
+ if (strne("okay",O_VALC(o)))
+ call error (2, O_VALC(o))
+ }
+ call evvfree (o)
+
+ } then
+ if (IP_OUTPUT(ip) != IP_INFO)
+ call erract (EA_FATAL)
+end
+
+
+# IP_DO_COMMENT - Process a comment line in the format database.
+
+procedure ip_do_comment (ip, comstr)
+
+pointer ip #i task struct pointer
+char comstr[ARB] #i comment to add
+
+pointer sp, buf
+
+begin
+ # Copy the comment line to the comment block.
+ if (IP_COMPTR(ip) == NULL)
+ call calloc (IP_COMPTR(ip), SZ_COMMENT, TY_CHAR)
+
+ if (COMMENT(ip) == '\0') {
+ call strcpy ("\t", COMMENT(ip), SZ_LINE)
+ call strcat (comstr, COMMENT(ip), SZ_LINE)
+ } else {
+ call smark (sp)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+
+ Memc[buf] = '\0'
+ call strcpy ("\t", Memc[buf], SZ_LINE)
+ call strcat (comstr, Memc[buf], SZ_LINE)
+ call strcat ("\n", Memc[buf], SZ_LINE)
+ call strcat (COMMENT(ip), Memc[buf], SZ_COMMENT)
+
+ call strcpy (Memc[buf], COMMENT(ip), SZ_COMMENT)
+
+ call sfree (sp)
+ }
+end
+
+
+# IP_INITOP - Initialize an operand pointer to the requested values
+
+procedure ip_initop (o, len, type)
+
+pointer o #u operand pointer
+int len #i length of array
+int type #i data type of operand
+
+begin
+ O_LEN(o) = len
+ O_TYPE(o) = type
+ if (len > 1)
+ call calloc (O_VALP(o), len, type)
+end
diff --git a/pkg/dataio/import/generic/ipfio.x b/pkg/dataio/import/generic/ipfio.x
new file mode 100644
index 00000000..2977d8cb
--- /dev/null
+++ b/pkg/dataio/import/generic/ipfio.x
@@ -0,0 +1,569 @@
+include <mach.h>
+include <fset.h>
+include "../import.h"
+
+define DEBUG false
+
+
+# IP_GSTR -- Get a string of the specifed length from the given offset.
+
+procedure ip_gstr (fd, offset, len, outstr)
+
+int fd
+int offset
+int len
+char outstr[ARB]
+
+int nstat, read()
+pointer sp, buf
+
+begin
+ call smark (sp)
+ call salloc (buf, len+2, TY_CHAR)
+ call aclrc (Memc[buf], len+2)
+ call aclrc (outstr, len+2)
+
+ call ip_lseek (fd, offset)
+ nstat = read (fd, Memc[buf], len)
+
+ if (mod(offset,2) == 0 && offset > 1)
+ call bytmov (Memc[buf], 2, Memc[buf], 1, len)
+ call chrupk (Memc[buf], 1, outstr, 1, len)
+
+ if (DEBUG) { call eprintf ("ip_gstr: :%s: len=%d\n");
+ call pargstr(outstr) ; call pargi (len) }
+ call sfree (sp)
+end
+
+
+# IP_GETB -- Get a byte from the given offset.
+
+short procedure ip_getb (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+short val
+char buf[2]
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, buf, 2)
+
+ if (mod(offset,2) == 0)
+ call bytmov (buf, 2, buf, 1, 2)
+ call chrupk (buf, 1, buf, 1, 2)
+
+ if (DEBUG) { call eprintf ("ip_getb: %d\n"); call pargs(buf[1]) }
+ if (buf[1] < 0)
+ val = buf[1] + 256
+ else
+ val = buf[1]
+ return (val)
+end
+
+
+# IP_GETU -- Get a unsigned short integer from the given offset.
+
+int procedure ip_getu (fd, offset)
+
+int fd
+int offset
+
+int val
+short ip_gets()
+
+begin
+ val = ip_gets (fd, offset)
+ if (val < 0)
+ val = val + 65536
+ return (val)
+end
+
+# IP_GET[silrd] -- Get a value of <type> from the given offset.
+
+
+
+short procedure ip_gets (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+short val
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, val, SZ_SHORT * SZB_CHAR)
+
+ if (DEBUG) { call eprintf ("ip_get: %g\n"); call pargs(val) }
+ return (val)
+end
+
+
+int procedure ip_geti (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+int val
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, val, SZ_INT32 * SZB_CHAR)
+ if (SZ_INT != SZ_INT32)
+ call iupk32 (val, val, 1)
+
+ if (DEBUG) { call eprintf ("ip_get: %g\n"); call pargi(val) }
+ return (val)
+end
+
+
+long procedure ip_getl (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+long val
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, val, SZ_INT32 * SZB_CHAR)
+ if (SZ_INT != SZ_INT32)
+ call iupk32 (val, val, 1)
+
+ if (DEBUG) { call eprintf ("ip_get: %g\n"); call pargl(val) }
+ return (val)
+end
+
+
+real procedure ip_getr (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+real val
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, val, SZ_REAL * SZB_CHAR)
+ call ieeupkr (val)
+
+ if (DEBUG) { call eprintf ("ip_get: %g\n"); call pargr(val) }
+ return (val)
+end
+
+
+double procedure ip_getd (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+double val
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, val, SZ_DOUBLE * SZB_CHAR)
+ call ieeupkd (val)
+
+ if (DEBUG) { call eprintf ("ip_get: %g\n"); call pargd(val) }
+ return (val)
+end
+
+
+# IP_GETN -- Get a native floating point number from the given offset.
+
+real procedure ip_getn (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+real rval
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, rval, SZ_REAL)
+
+ if (DEBUG) { call eprintf ("ip_getn: %g\n"); call pargr(rval) }
+ return (rval)
+end
+
+
+# IP_GETN8 -- Get a native double precision floating point number from the
+# given offset.
+
+double procedure ip_getn8 (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+double dval
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, dval, SZ_DOUBLE)
+
+ if (DEBUG) { call eprintf ("ip_getn8: %g\n"); call pargd(dval) }
+ return (dval)
+end
+
+
+# IP_AGETB -- Get an array of bytes from the file. The data pointer is
+# allocated if necessary and contains the data on output.
+
+procedure ip_agetb (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+pointer sp, buf
+int fp, nval, nstat
+int ip_lnote(), read()
+
+begin
+ fp = ip_lnote(fd)
+ if (mod(fp,2) == 0 && fp != 1)
+ nval = len
+ else
+ nval = len + 1
+
+ call smark (sp)
+ call salloc (buf, nval, TY_CHAR)
+
+ if (ptr == NULL)
+ call malloc (ptr, nval * SZB_CHAR, TY_CHAR)
+ nstat = read (fd, Memc[buf], nval / SZB_CHAR + 1)
+
+ fp = ip_lnote(fd)
+ if (mod(fp,2) == 0 && fp != 1)
+ call bytmov (Memc[buf], 2, Memc[buf], 1, nval)
+ call achtbc (Memc[buf], Memc[ptr], len)
+
+ call sfree (sp)
+end
+
+
+# IP_AGETU -- Get an array of <type> from the file. The data pointer is
+# allocated if necessary and contains the data on output.
+
+procedure ip_agetu (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+begin
+ call ip_agets (fd, ptr, len)
+ call achtsu (Mems[ptr], Mems[ptr], len)
+end
+
+
+# IP_AGET[silrd] -- Get an array of <type> from the file. The data pointer is
+# allocated if necessary and contains the data on output.
+
+
+procedure ip_agets (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+int nstat
+int read()
+
+begin
+ if (ptr == NULL)
+ call malloc (ptr, len, TY_SHORT)
+ nstat = read (fd, Mems[ptr], len * SZ_SHORT)
+end
+
+
+procedure ip_ageti (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+int nstat
+int read()
+
+begin
+ if (ptr == NULL)
+ call malloc (ptr, len, TY_INT)
+ nstat = read (fd, Memi[ptr], len * SZ_INT32)
+ if (SZ_INT != SZ_INT32)
+ call iupk32 (Memi[ptr], Memi[ptr], len)
+end
+
+
+procedure ip_agetl (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+int nstat
+int read()
+
+begin
+ if (ptr == NULL)
+ call malloc (ptr, len, TY_LONG)
+ nstat = read (fd, Meml[ptr], len * SZ_INT32)
+ if (SZ_INT != SZ_INT32)
+ call iupk32 (Meml[ptr], Meml[ptr], len)
+end
+
+
+procedure ip_agetr (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+int nstat
+int read()
+
+begin
+ if (ptr == NULL)
+ call malloc (ptr, len, TY_REAL)
+ nstat = read (fd, Memr[ptr], len * SZ_REAL)
+ call ieevupkr (Memr[ptr], Memr[ptr], len)
+end
+
+
+procedure ip_agetd (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+int nstat
+int read()
+
+begin
+ if (ptr == NULL)
+ call malloc (ptr, len, TY_DOUBLE)
+ nstat = read (fd, Memd[ptr], len * SZ_DOUBLE)
+ call ieevupkd (Memd[ptr], Memd[ptr], len)
+end
+
+
+
+# IP_AGETN -- Get an array of native floats from the file. The data pointer is
+# allocated if necessary and contains the data on output.
+
+procedure ip_agetn (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+int nstat
+int read()
+
+begin
+ if (ptr == NULL)
+ call malloc (ptr, len, TY_REAL)
+ nstat = read (fd, Memr[ptr], len * SZ_REAL)
+end
+
+
+# IP_AGETN8 -- Get an array of native doubles from the file. The data pointer
+# is allocated if necessary and contains the data on output.
+
+procedure ip_agetn8 (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+int nstat
+int read()
+
+begin
+ if (ptr == NULL)
+ call malloc (ptr, len, TY_DOUBLE)
+ nstat = read (fd, Memd[ptr], len * SZ_DOUBLE)
+end
+
+
+# -----------------------------------------------------------------
+# ------------------ UTILITY FILE I/O FUNCTIONS -------------------
+# -----------------------------------------------------------------
+
+
+define BLKSIZE 1024
+
+# IP_LINE -- Return the offset of the start of the given line number.
+
+int procedure ip_line (fd, line)
+
+int fd #i input file descriptor
+int line #i line number to search
+
+pointer sp, cbuf, buf
+int nl, offset, i, nread, fsize
+
+int read(), fstati()
+
+define done_ 99
+define err_ 98
+
+begin
+ if (line == 1) {
+ return (1)
+ } else {
+ call smark (sp)
+ call salloc (buf, BLKSIZE, TY_CHAR)
+ call salloc (cbuf, BLKSIZE, TY_CHAR)
+
+ # Rewind file descriptor
+ call ip_lseek (fd, BOF)
+ nl = 1
+ offset = 1
+
+ nread = BLKSIZE / SZB_CHAR
+ fsize = fstati (fd, F_FILESIZE)
+ while (read (fd, Memc[buf], nread) != EOF) {
+ # Convert it to spp chars.
+ call ip_lskip (fd, nread)
+ call chrupk (Memc[buf], 1, Memc[cbuf], 1, BLKSIZE)
+ do i = 1, BLKSIZE {
+ if (Memc[cbuf+i-1] == '\n') {
+ nl = nl + 1
+ offset = offset + 1
+ if (nl == line)
+ goto done_
+ } else
+ offset = offset + 1
+ if (offset >= fsize)
+ goto err_
+ }
+ }
+err_ call sfree (sp)
+ call ip_lseek (fd, BOF)
+ return (ERR)
+
+done_ if (DEBUG) { call eprintf("ip_line: '%s'\n"); call pargi(offset) }
+ call sfree (sp)
+ call ip_lseek (fd, offset)
+ return (offset)
+ }
+end
+
+
+# IP_LOCATE -- Return the offset of the start of the given pattern.
+
+int procedure ip_locate (fd, offset, pattern)
+
+int fd #i input file descriptor
+int offset #i offset to begin search
+char pattern[ARB] #i pattern to locate
+
+pointer sp, cbuf, buf
+int fsize, nread, patlen, cur_offset, loc
+
+int fstati(), read(), strsearch(), strlen()
+
+define done_ 99
+
+begin
+ # Rewind file descriptor
+ call ip_lseek (fd, offset)
+ cur_offset = offset
+
+ call smark (sp)
+ call salloc (buf, BLKSIZE, TY_CHAR)
+ call salloc (cbuf, BLKSIZE, TY_CHAR)
+
+ if (DEBUG) { call eprintf("ip_loc: offset %d\n"); call pargi(offset)}
+
+ nread = BLKSIZE / SZB_CHAR
+ fsize = fstati (fd, F_FILESIZE)
+ patlen = strlen (pattern)
+ while (read (fd, Memc[buf], nread) != EOF) {
+ # Convert it to spp chars.
+ call ip_lskip (fd, nread)
+ call chrupk (Memc[buf], 1, Memc[cbuf], 1, BLKSIZE)
+ loc = strsearch (Memc[cbuf], pattern)
+ if (loc != 0) {
+ cur_offset = cur_offset + loc - 1 - patlen
+ goto done_
+ } else {
+ # Allow some overlap in case the pattern broke over the blocks.
+ cur_offset = cur_offset + BLKSIZE - 2 * patlen
+ call ip_lseek (fd, cur_offset)
+ if (cur_offset + BLKSIZE > fsize)
+ nread = fsize - cur_offset + 1
+ }
+ }
+ call sfree (sp)
+ call ip_lseek (fd, BOF)
+ return (ERR)
+
+done_ if (DEBUG) { call eprintf("ip_loc: %d\n"); call pargi(cur_offset)}
+ call sfree (sp)
+ call ip_lseek (fd, offset)
+ return (cur_offset)
+end
+
+
+# IP_LSEEK -- Set the file position as a byte offset.
+
+procedure ip_lseek (fd, offset)
+
+int fd #i file descriptor
+int offset #i requested offset
+
+long cur_offset, where, fsize
+int fstati()
+common /fiocom/ cur_offset
+
+begin
+ if (offset == BOF || offset == ERR) {
+ cur_offset = 1
+ call seek (fd, BOF)
+ } else {
+ fsize = fstati (fd, F_FILESIZE) * SZB_CHAR
+ cur_offset = min (fsize, offset)
+ where = min (fsize, (offset/SZB_CHAR+mod(offset,2)))
+ call seek (fd, where)
+ }
+end
+
+
+# IP_LNOTE -- Note the file position as a byte offset.
+
+int procedure ip_lnote (fd)
+
+int fd #i file descriptor (unused)
+
+long cur_offset
+common /fiocom/ cur_offset
+
+begin
+ return (cur_offset)
+end
+
+
+# IP_LSKIP -- Bump the file position by a byte offset.
+
+procedure ip_lskip (fd, skip)
+
+int fd #i file descriptor
+int skip
+
+long cur_offset
+common /fiocom/ cur_offset
+
+begin
+ call ip_lseek (fd, cur_offset+skip)
+end
diff --git a/pkg/dataio/import/generic/ipobands.x b/pkg/dataio/import/generic/ipobands.x
new file mode 100644
index 00000000..65c6c1c4
--- /dev/null
+++ b/pkg/dataio/import/generic/ipobands.x
@@ -0,0 +1,375 @@
+include <error.h>
+include <mach.h>
+include <evvexpr.h>
+include <fset.h>
+include "../import.h"
+include "../ipfcn.h"
+
+define DEBUG false
+define VDEBUG false
+
+
+# IP_GETOP -- Called by evvexpr to get an operand.
+
+procedure ip_getop (ip, opname, o)
+
+pointer ip #i task struct pointer
+char opname[ARB] #i operand name to retrieve
+pointer o #o output operand pointer
+
+int i, nops, found, optype
+pointer sp, buf
+pointer op
+
+int fstati(), ip_ptype(), strlen(), strncmp()
+bool streq()
+
+begin
+ # First see if it's one of the special file operands.
+ if (opname[1] == '$') {
+ if (strncmp(opname, "$FSIZE", 3) == 0) {
+ O_LEN(o) = 0
+ O_TYPE(o) = TY_INT
+ O_VALI(o) = fstati (IP_FD(ip), F_FILESIZE) * SZB_CHAR
+ } else if (strncmp(opname, "$FNAME", 3) == 0) {
+ call smark (sp)
+ call salloc (buf, SZ_FNAME, TY_CHAR)
+
+ call fstats (IP_FD(ip), F_FILENAME, Memc[buf], SZ_FNAME)
+
+ O_TYPE(o) = TY_CHAR
+ O_LEN(o) = strlen (Memc[buf]) + 1
+ call malloc (O_VALP(o), O_LEN(o), TY_CHAR)
+ call strcpy (Memc[buf], O_VALC(o), i)
+ call sfree (sp)
+ }
+
+ return
+ }
+
+ nops = IP_NPIXT(ip)
+ found = NO
+ do i = 1, nops {
+ # Search for operand name which matches requested value.
+ op = PTYPE(ip,i)
+ if (streq (Memc[IO_TAG(op)],opname)) {
+ found = YES
+ break
+ }
+ }
+
+ if (VDEBUG) {
+ call eprintf ("getop: opname=%s tag=%s found=%d ")
+ call pargstr(opname) ; call pargstr(Memc[IO_TAG(op)])
+ call pargi(found)
+ if (found == YES) call zzi_prop (op)
+ }
+
+ if (found == YES) {
+ # Copy operand descriptor to 'o'
+ optype = ip_ptype (IO_TYPE(op), IO_NBYTES(op))
+ switch (optype) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ O_LEN(o) = IO_NPIX(op)
+ O_TYPE(o) = TY_SHORT
+ call malloc (O_VALP(o), IO_NPIX(op), TY_SHORT)
+ call amovs (Mems[IO_DATA(op)], Mems[O_VALP(o)], IO_NPIX(op))
+
+ case TY_INT:
+ O_LEN(o) = IO_NPIX(op)
+ O_TYPE(o) = TY_INT
+ call malloc (O_VALP(o), IO_NPIX(op), TY_INT)
+ call amovi (Memi[IO_DATA(op)], Memi[O_VALP(o)], IO_NPIX(op))
+
+ case TY_LONG:
+ O_LEN(o) = IO_NPIX(op)
+ O_TYPE(o) = TY_LONG
+ call malloc (O_VALP(o), IO_NPIX(op), TY_LONG)
+ call amovl (Meml[IO_DATA(op)], Meml[O_VALP(o)], IO_NPIX(op))
+
+ case TY_REAL:
+ O_LEN(o) = IO_NPIX(op)
+ O_TYPE(o) = TY_REAL
+ call malloc (O_VALP(o), IO_NPIX(op), TY_REAL)
+ call amovr (Memr[IO_DATA(op)], Memr[O_VALP(o)], IO_NPIX(op))
+
+ case TY_DOUBLE:
+ O_LEN(o) = IO_NPIX(op)
+ O_TYPE(o) = TY_DOUBLE
+ call malloc (O_VALP(o), IO_NPIX(op), TY_DOUBLE)
+ call amovd (Memd[IO_DATA(op)], Memd[O_VALP(o)], IO_NPIX(op))
+
+ }
+
+ } else {
+ call smark (sp)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+ call sprintf (Memc[buf], SZ_LINE, "Unknown outbands operand `%s'\n")
+ call pargstr(opname)
+ call sfree (sp)
+ call error (1, Memc[buf])
+ }
+end
+
+
+# IP_EVALUATE -- Evaluate the outbands expression.
+
+pointer procedure ip_evaluate (ip, expr)
+
+pointer ip #i task struct pointer
+char expr[ARB] #i expression to be evaluated
+
+pointer o # operand pointer to result
+
+int locpr()
+pointer evvexpr()
+extern ip_getop(), ip_obfcn()
+errchk evvexpr
+
+begin
+ if (DEBUG) { call eprintf("ip_eval: expr='%s'\n") ; call pargstr(expr) }
+
+ # Evaluate the expression.
+ iferr {
+ o = evvexpr (expr, locpr(ip_getop), ip, locpr(ip_obfcn), ip,
+ EV_RNGCHK)
+ } then
+ call erract (EA_FATAL)
+
+ return (o)
+end
+
+
+# IP_OBFCN -- Called by evvexpr to execute import outbands special functions.
+
+procedure ip_obfcn (ip, fcn, args, nargs, o)
+
+pointer ip #i task struct pointer
+char fcn[ARB] #i function to be executed
+pointer args[ARB] #i argument list
+int nargs #i number of arguments
+pointer o #o operand pointer
+
+pointer sp, buf
+pointer r, g, b, gray, color, cmap
+int i, len, v_nargs, func
+
+int or(), strdic()
+bool strne()
+
+define setop_ 99
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_FNAME, TY_CHAR)
+
+ # Lookup function in dictionary.
+ func = strdic (fcn, Memc[buf], SZ_LINE, OB_FUNCTIONS)
+ if (func > 0 && strne(fcn,Memc[buf]))
+ func = 0
+
+ # Abort if the function is not known.
+ if (func <= 0)
+ call xev_error1 ("unknown function `%s' called", fcn)
+
+ # Verify the correct number of arguments, negative value means a
+ # variable number of args, handle it in the evaluation.
+ switch (func) {
+ case GRAY, GREY:
+ v_nargs = 3
+ case FLIPX, FLIPY:
+ v_nargs = 1
+ case RED, GREEN, BLUE:
+ v_nargs = 1
+ }
+ if (v_nargs > 0 && nargs != v_nargs)
+ call xev_error2 ("function `%s' requires %d arguments",
+ fcn, v_nargs)
+ else if (v_nargs < 0 && nargs < abs(v_nargs))
+ call xev_error2 ("function `%s' requires at least %d arguments",
+ fcn, abs(v_nargs))
+
+ if (DEBUG) {
+ call eprintf ("obfcn: nargs=%d func=%d\n")
+ call pargi (nargs) ; call pargi (func)
+ do i = 1, nargs { call eprintf ("\t") ; call zzi_pevop (args[i]) }
+ call flush (STDERR)
+ }
+
+ # Evaluate the function.
+ switch (func) {
+ case GRAY, GREY:
+ # evaluate expression for NTSC grayscale.
+ r = O_VALP(args[1])
+ g = O_VALP(args[2])
+ b = O_VALP(args[3])
+ len = O_LEN(args[1]) - 1
+ O_LEN(o) = len + 1
+ O_TYPE(o) = TY_REAL
+ call malloc (O_VALP(o), len+1, TY_REAL)
+ gray = O_VALP(o)
+ switch (O_TYPE(args[1])) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ do i = 0, len {
+ Memr[gray+i] = R_COEFF * Mems[r+i] +
+ G_COEFF * Mems[g+i] +
+ B_COEFF * Mems[b+i]
+ }
+
+ case TY_INT:
+ do i = 0, len {
+ Memr[gray+i] = R_COEFF * Memi[r+i] +
+ G_COEFF * Memi[g+i] +
+ B_COEFF * Memi[b+i]
+ }
+
+ case TY_LONG:
+ do i = 0, len {
+ Memr[gray+i] = R_COEFF * Meml[r+i] +
+ G_COEFF * Meml[g+i] +
+ B_COEFF * Meml[b+i]
+ }
+
+ case TY_REAL:
+ do i = 0, len {
+ Memr[gray+i] = R_COEFF * Memr[r+i] +
+ G_COEFF * Memr[g+i] +
+ B_COEFF * Memr[b+i]
+ }
+
+ case TY_DOUBLE:
+ do i = 0, len {
+ Memr[gray+i] = R_COEFF * Memd[r+i] +
+ G_COEFF * Memd[g+i] +
+ B_COEFF * Memd[b+i]
+ }
+
+ }
+
+ case RED:
+ # Get the red colormap component of the image.
+ cmap = IP_CMAP(ip)
+ if (func <= 0)
+ call xev_error1 ("No colormap in image for function `%s'", fcn)
+ r = O_VALP(args[1])
+ len = O_LEN(args[1]) - 1
+ O_LEN(o) = len + 1
+ O_TYPE(o) = TY_SHORT
+ call malloc (O_VALP(o), len+1, TY_SHORT)
+ color = O_VALP(o)
+ switch (O_TYPE(args[1])) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_RED,Mems[r+i]+1)
+
+ case TY_INT:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_RED,Memi[r+i]+1)
+
+ case TY_LONG:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_RED,Meml[r+i]+1)
+
+ }
+
+ case GREEN:
+ # Get the blue colormap component of the image.
+ cmap = IP_CMAP(ip)
+ if (func <= 0)
+ call xev_error1 ("No colormap in image for function `%s'", fcn)
+ g = O_VALP(args[1])
+ len = O_LEN(args[1]) - 1
+ O_LEN(o) = len + 1
+ O_TYPE(o) = TY_SHORT
+ call malloc (O_VALP(o), len+1, TY_SHORT)
+ color = O_VALP(o)
+ switch (O_TYPE(args[1])) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_GREEN,Mems[g+i]+1)
+
+ case TY_INT:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_GREEN,char(Memi[g+i]+1))
+
+ case TY_LONG:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_GREEN,char(Meml[g+i]+1))
+
+ }
+
+ case BLUE:
+ # Get the blue colormap component of the image.
+ cmap = IP_CMAP(ip)
+ if (func <= 0)
+ call xev_error1 ("No colormap in image for function `%s'", fcn)
+ b = O_VALP(args[1])
+ len = O_LEN(args[1]) - 1
+ O_LEN(o) = len + 1
+ O_TYPE(o) = TY_SHORT
+ call malloc (O_VALP(o), len+1, TY_SHORT)
+ color = O_VALP(o)
+ switch (O_TYPE(args[1])) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_BLUE,Mems[b+i]+1)
+
+ case TY_INT:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_BLUE,char(Memi[b+i]+1))
+
+ case TY_LONG:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_BLUE,char(Meml[b+i]+1))
+
+ }
+
+ case FLIPX:
+ # Set flag to reverse pixel order on output.
+ IP_FLIP(ip) = or (IP_FLIP(ip), FLIP_X)
+ goto setop_
+
+ case FLIPY:
+ # Set flag to write image from bottom to top.
+ IP_FLIP(ip) = or (IP_FLIP(ip), FLIP_Y)
+
+ # Copy argument operand descriptor to 'o'
+setop_ switch (O_TYPE(args[1])) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ O_LEN(o) = O_LEN(args[1])
+ O_TYPE(o) = TY_SHORT
+ call malloc (O_VALP(o), O_LEN(args[1]), TY_SHORT)
+ call amovs (Mems[O_VALP(ARGS[1])], Mems[O_VALP(o)], O_LEN(o))
+
+ case TY_INT:
+ O_LEN(o) = O_LEN(args[1])
+ O_TYPE(o) = TY_INT
+ call malloc (O_VALP(o), O_LEN(args[1]), TY_INT)
+ call amovi (Memi[O_VALP(args[1])], Memi[O_VALP(o)], O_LEN(o))
+
+ case TY_LONG:
+ O_LEN(o) = O_LEN(args[1])
+ O_TYPE(o) = TY_LONG
+ call malloc (O_VALP(o), O_LEN(args[1]), TY_LONG)
+ call amovl (Meml[O_VALP(args[1])], Meml[O_VALP(o)], O_LEN(o))
+
+ case TY_REAL:
+ O_LEN(o) = O_LEN(args[1])
+ O_TYPE(o) = TY_REAL
+ call malloc (O_VALP(o), O_LEN(args[1]), TY_REAL)
+ call amovr (Memr[O_VALP(args[1])], Memr[O_VALP(o)], O_LEN(o))
+
+ case TY_DOUBLE:
+ O_LEN(o) = O_LEN(args[1])
+ O_TYPE(o) = TY_DOUBLE
+ call malloc (O_VALP(o), O_LEN(args[1]), TY_DOUBLE)
+ call amovd (Memd[O_VALP(args[1])], Memd[O_VALP(o)], O_LEN(o))
+
+ }
+
+ }
+
+ if (DEBUG) { call zzi_pevop (o) }
+
+ call sfree (sp)
+end
diff --git a/pkg/dataio/import/generic/ipproc.x b/pkg/dataio/import/generic/ipproc.x
new file mode 100644
index 00000000..def48b1c
--- /dev/null
+++ b/pkg/dataio/import/generic/ipproc.x
@@ -0,0 +1,921 @@
+include <mach.h>
+include <imhdr.h>
+include <evvexpr.h>
+include "../import.h"
+
+define DEBUG false
+
+
+# IP_PRBAND -- Process a band interleaved file.
+
+procedure ip_prband (ip, fd, im, cmap)
+
+pointer ip #i task struct pointer
+int fd #i inpout file descriptor
+pointer im #i output image pointer
+pointer cmap #i colormap pointer
+
+int i, j, nlines, npix
+int optype, nbytes_pix, percent
+int cur_offset, band_offset, line_offset
+
+int ip_ptype()
+long ip_lnote()
+
+begin
+ # Rewind the file and skip header pixels.
+ call ip_lseek (fd, BOF)
+ call ip_lseek (fd, IP_HSKIP(ip)+1)
+
+ # Compute the offset between the same pixel in different bands. This
+ # is the area of the image plus any image padding, computed as a
+ # byte offset.
+ optype = ip_ptype (IO_TYPE(PTYPE(ip,1)),IO_NBYTES(PTYPE(ip,1)))
+ switch (optype) {
+ case TY_UBYTE: nbytes_pix = 1
+ case TY_USHORT, TY_SHORT: nbytes_pix = SZB_CHAR * SZ_SHORT
+ case TY_INT: nbytes_pix = SZB_CHAR * SZ_INT32
+ case TY_LONG: nbytes_pix = SZB_CHAR * SZ_LONG
+ case TY_REAL: nbytes_pix = SZB_CHAR * SZ_REAL
+ case TY_DOUBLE: nbytes_pix = SZB_CHAR * SZ_DOUBLE
+ }
+ band_offset = (IP_AXLEN(ip,1) * (IP_AXLEN(ip,2)-1)) +
+ ((IP_LSKIP(ip) + IP_LPAD(ip)) * (IP_AXLEN(ip,2)-1)) +
+ IP_BSKIP(ip)
+ band_offset = (band_offset * nbytes_pix) #+ 1
+
+ if (DEBUG) {
+ call eprintf ("ip_prband: band_offset=%d curpos=%d\n")
+ call pargi(band_offset) ; call pargi(ip_lnote(fd))
+ call zzi_prstruct ("ip_prband", ip)
+ }
+
+ # Patch up the pixtype param if needed.
+ call ip_fix_pixtype (ip)
+
+ # See if we need to create any outbands operands if the user didn't.
+ if (IP_NBANDS(ip) == ERR)
+ call ip_fix_outbands (ip)
+
+ # Loop over the image lines.
+ nlines = IP_AXLEN(ip,2)
+ npix = IP_AXLEN(ip,1)
+ percent = 0
+ do i = 1, nlines {
+ # Skip pixels at front of line
+ line_offset = ip_lnote (fd)
+ if (IP_LSKIP(ip) != 0)
+ call ip_lskip (fd, IP_LSKIP(ip))
+
+ # Read pixels in the line and save as operand.
+ call ip_rdline (ip, fd, 1, npix, cmap)
+
+ # Skip pixels at end of line.
+ if (IP_LPAD(ip) != 0)
+ call ip_lskip (fd, IP_LPAD(ip))
+ cur_offset = ip_lnote (fd)
+
+ # Loop over each of the remaining pixtypes.
+ do j = 2, IP_NPIXT(ip) {
+ # Seek to offset of next band (i.e. line_offset + band_offset).
+ call ip_lskip (fd, band_offset)
+ if (IP_LSKIP(ip) != 0)
+ call ip_lskip (fd, IP_LSKIP(ip))
+ call ip_rdline (ip, fd, j, npix, cmap) # read pixels in the line
+ if (IP_LPAD(ip) != 0)
+ call ip_lskip (fd, IP_LPAD(ip))
+ }
+
+ # Evaluate and write the outbands expressions.
+ call ip_probexpr (ip, im, npix, i)
+
+ # Print percent done if being verbose
+ #if (IP_VERBOSE(ip) == YES)
+ call ip_pstat (ip, i, percent)
+
+ # Restore file pointer to cur_offset.
+ call ip_lseek (fd, cur_offset)
+ }
+ do i = 1, IP_NBANDS(ip)
+ call mfree (BUFFER(ip,i), IM_PIXTYPE(im))
+end
+
+
+# IP_PRLINE -- Process a line interleaved file.
+
+procedure ip_prline (ip, fd, im, cmap)
+
+pointer ip #i task struct pointer
+int fd #i inpout file descriptor
+pointer im #i output image pointer
+pointer cmap #i colormap pointer
+
+int i, j, nlines, npix, percent
+
+begin
+ # Rewind the file and skip header pixels.
+ call ip_lseek (fd, BOF)
+ call ip_lseek (fd, IP_HSKIP(ip)+1)
+
+ if (DEBUG) {
+ call eprintf ("ip_prline:\n")
+ call zzi_prstruct ("ip_prline", ip)
+ }
+
+ # Patch up the pixtype param if needed.
+ call ip_fix_pixtype (ip)
+
+ # See if we need to create any outbands operands if the user didn't.
+ if (IP_NBANDS(ip) == ERR)
+ call ip_fix_outbands (ip)
+
+ # Loop over the image lines.
+ nlines = IP_AXLEN(ip,2)
+ npix = IP_AXLEN(ip,1)
+ percent = 0
+ do i = 1, nlines {
+
+ do j = 1, IP_NPIXT(ip) {
+ # Skip pixels at front of line
+ call ip_lskip (fd, IP_LSKIP(ip))
+
+ # Read pixels in the line and save as operand.
+ call ip_rdline (ip, fd, j, npix, cmap)
+
+ # Skip pixels at end of line.
+ call ip_lskip (fd, IP_LPAD(ip))
+ }
+
+ # Evaluate and write the outbands expressions.
+ call ip_probexpr (ip, im, npix, i)
+
+ # Print percent done if being verbose
+ #if (IP_VERBOSE(ip) == YES)
+ call ip_pstat (ip, i, percent)
+ }
+ do i = 1, IP_NBANDS(ip)
+ call mfree (BUFFER(ip,i), IM_PIXTYPE(im))
+end
+
+
+# IP_PRPIX -- Process a pixel interleaved file.
+
+procedure ip_prpix (ip, fd, im, cmap)
+
+pointer ip #i task struct pointer
+int fd #i inpout file descriptor
+pointer im #i output image pointer
+pointer cmap #i colormap pointer
+
+pointer op, data
+int i, swap, optype, nlines
+int percent, npix, totpix
+
+int and(), ip_ptype()
+
+begin
+ # Rewind the file and skip header pixels.
+ call ip_lseek (fd, BOF)
+ call ip_lseek (fd, IP_HSKIP(ip)+1)
+
+ if (DEBUG) { call eprintf ("ip_prpix: ") }
+
+ # See if we need to create any outbands operands if the user didn't.
+ if (IP_NBANDS(ip) == ERR)
+ call ip_fix_outbands (ip)
+
+ # Allocate the pixtype data pointers.
+ npix = IP_AXLEN(ip,1)
+ nlines = IP_NPIXT(ip)
+ do i = 1, nlines {
+ op = PTYPE(ip,i)
+ optype = ip_ptype (IO_TYPE(op),IO_NBYTES(op))
+ IO_NPIX(op) = npix
+ if (IO_DATA(op) == NULL)
+ if (optype == TY_UBYTE)
+ call malloc (IO_DATA(op), npix, TY_SHORT)
+ else
+ call malloc (IO_DATA(op), npix, optype)
+ }
+
+ # Loop over the image lines.
+ nlines = IP_AXLEN(ip,2)
+ totpix = npix * IP_NPIXT(ip)
+ swap = IP_SWAP(ip)
+ percent = 0
+ if (DEBUG) {
+ call zzi_prstruct ("ip_prpix", ip)
+ call eprintf ("nl=%d np=%d tp=%d:\n")
+ call pargi(nlines) ; call pargi(npix) ; call pargi(totpix)
+ }
+ do i = 1, nlines {
+
+ # Skip pixels at front of line
+ call ip_lskip (fd, IP_LSKIP(ip))
+
+ # Read pixels in the line.
+ switch (optype) {
+ case TY_UBYTE:
+ call ip_agetb (fd, data, totpix)
+ call ip_lskip (fd, totpix)
+ # Apply a colormap to the bytes. In general a pixel-interleaved
+ # file is a 24-bit True Color image, but maybe this is a
+ # 3-D color index file?
+ if (cmap != NULL && IP_USE_CMAP(ip) == YES)
+ call ip_gray_cmap (Memc[data], totpix, cmap)
+
+ case TY_USHORT:
+ call ip_agetu (fd, data, totpix)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2) {
+ call bswap2 (Mems[data], 1, Mems[data], 1,
+ (totpix*(SZ_SHORT*SZB_CHAR)))
+ }
+ call ip_lskip (fd, (totpix * (SZB_CHAR * SZ_SHORT)))
+
+
+ case TY_SHORT:
+ call ip_agets (fd, data, totpix)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2) {
+ call bswap2 (Mems[data], 1, Mems[data], 1,
+ (totpix*(SZ_SHORT*SZB_CHAR)))
+ }
+
+ call ip_lskip (fd, (totpix * (SZB_CHAR * SZ_SHORT)))
+
+ case TY_INT:
+ call ip_ageti (fd, data, totpix)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I4) == S_I4) {
+ if (SZ_INT != SZ_INT32) {
+ call ipak32 (Memi[data], Memi[data], totpix)
+ call bswap4 (Memi[data], 1, Memi[data], 1,
+ (totpix*(SZ_INT32*SZB_CHAR)))
+ } else {
+ call bswap4 (Memi[data], 1, Memi[data], 1,
+ (totpix*(SZ_INT*SZB_CHAR)))
+ }
+ }
+
+ call ip_lskip (fd, (totpix * (SZB_CHAR * SZ_INT32)))
+
+ case TY_LONG:
+ call ip_agetl (fd, data, totpix)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I4) == S_I4) {
+ if (SZ_INT != SZ_INT32) {
+ call ipak32 (Meml[data], Meml[data], totpix)
+ call bswap4 (Meml[data], 1, Meml[data], 1,
+ (totpix*(SZ_INT32*SZB_CHAR)))
+ } else {
+ call bswap4 (Meml[data], 1, Meml[data], 1,
+ (totpix*(SZ_INT*SZB_CHAR)))
+ }
+ }
+
+ call ip_lskip (fd, (totpix * (SZB_CHAR * SZ_INT32)))
+
+ case TY_REAL:
+ call ip_agetr (fd, data, totpix)
+ if (and(swap, S_ALL) == S_ALL) {
+ call bswap4 (Memr[data], 1, Memr[data], 1,
+ (totpix*(SZ_REAL*SZB_CHAR)))
+ }
+
+ call ip_lskip (fd, (totpix * (SZB_CHAR * SZ_REAL)))
+
+ case TY_DOUBLE:
+ call ip_agetd (fd, data, totpix)
+ if (and(swap, S_ALL) == S_ALL) {
+ call bswap8 (Memd[data], 1, Memd[data], 1,
+ (totpix*(SZ_DOUBLE*SZB_CHAR)))
+ }
+
+ call ip_lskip (fd, (totpix * (SZB_CHAR * SZ_DOUBLE)))
+
+ }
+
+ # Skip pixels at end of line.
+ call ip_lskip (fd, IP_LPAD(ip))
+
+ # Separate pixels into different vectors.
+ call ip_upkpix (ip, data, npix)
+
+ # Evaluate and write the outbands expressions.
+ call ip_probexpr (ip, im, npix, i)
+
+ # Print percent done if being verbose
+ #if (IP_VERBOSE(ip) == YES)
+ call ip_pstat (ip, i, percent)
+ }
+
+ if (optype == TY_UBYTE)
+ call mfree (data, TY_SHORT)
+ else
+ call mfree (data, optype)
+ do i = 1, IP_NBANDS(ip)
+ call mfree (BUFFER(ip,i), IM_PIXTYPE(im))
+end
+
+
+# IP_PROBEXPR -- Process each of the outbands expressions and write the result
+# to the output image.
+
+procedure ip_probexpr (ip, im, npix, line)
+
+pointer ip #i task struct pointer
+pointer im #i output image pointer
+int npix #i number of output pixels
+int line #i line number
+
+int i
+pointer out, ip_evaluate()
+
+begin
+ # Loop over outbands expressions.
+ do i = 1, IP_NBANDS(ip) {
+ # Evaluate outbands expression.
+ out = ip_evaluate (ip, O_EXPR(ip,i))
+
+ # Write bands to output image
+ if (IP_OUTPUT(ip) != IP_NONE)
+ call ip_wrline (ip, im, out, npix, line, i)
+
+ call evvfree (out)
+ }
+end
+
+
+# IP_RDLINE -- Read a line of pixels from the binary file.
+
+procedure ip_rdline (ip, fd, pnum, npix, cmap)
+
+pointer ip #i task struct pointer
+int fd #i input file descriptor
+int pnum #i pixtype number
+int npix #i number of pixels to read
+pointer cmap #i colormap pointer
+
+pointer op, data
+int swap, ptype
+
+int and(), ip_ptype()
+
+begin
+ # Read pixels in the line and save as operand.
+ op = PTYPE(ip,pnum)
+ ptype = ip_ptype (IO_TYPE(op), IO_NBYTES(op))
+ data = IO_DATA(op)
+ swap = IP_SWAP(ip)
+ IO_NPIX(op) = npix
+
+ switch (ptype) {
+ case TY_UBYTE:
+ call ip_agetb (fd, data, npix)
+ call ip_lskip (fd, npix)
+ # Apply a colormap to the bytes. If the colormap is non-null we
+ # assume the bytes are color indices into a colormap.
+ if (cmap != NULL && IP_USE_CMAP(ip) == YES)
+ call ip_gray_cmap (Memc[data], npix, cmap)
+
+ case TY_USHORT:
+ call ip_agetu (fd, data, npix)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2) {
+ call bswap2 (Mems[data], 1, Mems[data], 1,
+ (npix*(SZ_SHORT*SZB_CHAR)))
+ }
+ call ip_lskip (fd, (npix * (SZB_CHAR * SZ_SHORT)))
+
+ case TY_SHORT:
+ call ip_agets (fd, data, npix)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2) {
+ call bswap2 (Mems[data], 1, Mems[data], 1,
+ (npix*(SZ_SHORT*SZB_CHAR)))
+ }
+
+ call ip_lskip (fd, npix * (SZB_CHAR * SZ_SHORT))
+
+ case TY_INT:
+ call ip_ageti (fd, data, npix)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I4) {
+ if (SZ_INT != SZ_INT32) {
+ call ipak32 (Memi[data], Memi[data], npix)
+ call bswap4 (Memi[data], 1, Memi[data], 1,
+ (npix*(SZ_INT32*SZB_CHAR)))
+ } else {
+ call bswap4 (Memi[data], 1, Memi[data], 1,
+ (npix*(SZ_INT*SZB_CHAR)))
+ }
+ }
+
+ call ip_lskip (fd, npix * (SZB_CHAR * SZ_INT32))
+
+ case TY_LONG:
+ call ip_agetl (fd, data, npix)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I4) {
+ if (SZ_INT != SZ_INT32) {
+ call ipak32 (Meml[data], Meml[data], npix)
+ call bswap4 (Meml[data], 1, Meml[data], 1,
+ (npix*(SZ_INT32*SZB_CHAR)))
+ } else {
+ call bswap4 (Meml[data], 1, Meml[data], 1,
+ (npix*(SZ_LONG*SZB_CHAR)))
+ }
+ }
+
+ call ip_lskip (fd, npix * (SZB_CHAR * SZ_INT32))
+
+ case TY_REAL:
+ call ip_agetr (fd, data, npix)
+ if (and(swap, S_ALL) == S_ALL) {
+ call bswap4 (Memr[data], 1, Memr[data], 1,
+ (npix*(SZ_REAL*SZB_CHAR)))
+ }
+
+ call ip_lskip (fd, npix * (SZB_CHAR * SZ_REAL))
+
+ case TY_DOUBLE:
+ call ip_agetd (fd, data, npix)
+ if (and(swap, S_ALL) == S_ALL) {
+ call bswap8 (Memd[data], 1, Memd[data], 1,
+ (npix*(SZ_DOUBLE*SZB_CHAR)))
+ }
+
+ call ip_lskip (fd, npix * (SZB_CHAR * SZ_DOUBLE))
+
+ }
+ IO_DATA(op) = data
+end
+
+
+# IP_WRLINE -- Write a line of pixels to the output image. We handle image
+# flipping here to avoid possibly doing it several times while the outbands
+# expression is being evaluated.
+
+procedure ip_wrline (ip, im, out, npix, line, band)
+
+pointer ip #i task struct pointer
+pointer im #i output image pointer
+pointer out #i output operand pointer
+int npix #i number of pixels to read
+int line #i image line number
+int band #i image band number
+
+int i, lnum, type
+int nldone, blnum
+pointer sp, dptr, data, optr
+bool lastline
+
+int and()
+pointer imps3s(), imps3i(), imps3l(), imps3r(), imps3d()
+pointer ip_chtype()
+
+data blnum /0/
+data nldone /1/
+data lastline /false/
+
+begin
+ call smark (sp)
+
+ # The first thing we do is change the datatype of the operand to
+ # match the output pixel type.
+ if (IP_OUTTYPE(ip) != NULL) {
+ if (IP_OUTTYPE(ip) == O_TYPE(out))
+ optr = O_VALP(out)
+ else
+ optr = ip_chtype (out, IP_OUTTYPE(ip))
+ }
+ type = IP_OUTTYPE(ip)
+
+ # See if we're flipping image in Y, and adjust the line number.
+ if (and(IP_FLIP(ip),FLIP_Y) == FLIP_Y) {
+ lnum = IP_AXLEN(ip,2) - line + 1
+ if (band == 1)
+ blnum = IP_SZBUF(ip) - mod (line-1, IP_SZBUF(ip))
+ lastline = (lnum == 1)
+ } else {
+ lnum = line
+ if (band == 1)
+ blnum = blnum + 1
+ lastline = (lnum == IP_AXLEN(ip,2))
+ }
+
+ # See if we're flipping image in x, and reverse the pixels.
+ if (and(IP_FLIP(ip),FLIP_X) == FLIP_X) {
+ call salloc (dptr, npix, type)
+ do i = 1, npix {
+ switch (type) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ Mems[dptr+i-1] = Mems[optr+(npix-i)]
+
+ case TY_INT:
+ Memi[dptr+i-1] = Memi[optr+(npix-i)]
+
+ case TY_LONG:
+ Meml[dptr+i-1] = Meml[optr+(npix-i)]
+
+ case TY_REAL:
+ Memr[dptr+i-1] = Memr[optr+(npix-i)]
+
+ case TY_DOUBLE:
+ Memd[dptr+i-1] = Memd[optr+(npix-i)]
+
+ }
+ }
+ } else
+ dptr = optr
+
+ # Make sure the image pixtype is set.
+ if (IM_PIXTYPE(im) == NULL)
+ IM_PIXTYPE(im) = type
+
+ # Allocate the buffer pointer if needed.
+ if (BUFFER(ip,band) == NULL)
+ call calloc (BUFFER(ip,band), npix*IP_SZBUF(ip), IP_OUTTYPE(ip))
+
+ if (nldone < IP_SZBUF(ip) && !lastline) {
+ # Copy the image line to the buffer
+ data = BUFFER(ip,band)
+ switch (type) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ call amovs (Mems[dptr], Mems[data+((blnum-1)*npix)], npix)
+
+ case TY_INT:
+ call amovi (Memi[dptr], Memi[data+((blnum-1)*npix)], npix)
+
+ case TY_LONG:
+ call amovl (Meml[dptr], Meml[data+((blnum-1)*npix)], npix)
+
+ case TY_REAL:
+ call amovr (Memr[dptr], Memr[data+((blnum-1)*npix)], npix)
+
+ case TY_DOUBLE:
+ call amovd (Memd[dptr], Memd[data+((blnum-1)*npix)], npix)
+
+ }
+ if (band == IP_NBANDS(ip))
+ nldone = nldone + 1
+
+ } else {
+ # Write the buffer to the image as a section.
+ data = BUFFER(ip,band)
+ switch (type) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ call amovs (Mems[dptr], Mems[data+((blnum-1)*npix)], npix)
+ if (and(IP_FLIP(ip),FLIP_Y) == FLIP_Y) {
+ data = imps3s (im, 1, npix,
+ max(1,(lnum-IP_SZBUF(ip)+1)+IP_SZBUF(ip)-1),
+ max(1,lnum+min(nldone,IP_SZBUF(ip))-1),
+ band, band)
+ call amovs (Mems[BUFFER(ip,band)+(blnum-1)*npix],
+ Mems[data], npix*(IP_SZBUF(ip)-blnum+1))
+ } else {
+ data = imps3s (im, 1, npix,
+ min(IP_AXLEN(ip,2),(lnum-blnum+1)),
+ min(IP_AXLEN(ip,2),lnum),
+ band, band)
+ call amovs (Mems[BUFFER(ip,band)], Mems[data], npix*blnum)
+ }
+
+ case TY_INT:
+ call amovi (Memi[dptr], Memi[data+((blnum-1)*npix)], npix)
+ if (and(IP_FLIP(ip),FLIP_Y) == FLIP_Y) {
+ data = imps3i (im, 1, npix,
+ max(1,(lnum-IP_SZBUF(ip)+1)+IP_SZBUF(ip)-1),
+ max(1,lnum+min(nldone,IP_SZBUF(ip))-1),
+ band, band)
+ call amovi (Memi[BUFFER(ip,band)+(blnum-1)*npix],
+ Memi[data], npix*(IP_SZBUF(ip)-blnum+1))
+ } else {
+ data = imps3i (im, 1, npix,
+ min(IP_AXLEN(ip,2),(lnum-blnum+1)),
+ min(IP_AXLEN(ip,2),lnum),
+ band, band)
+ call amovi (Memi[BUFFER(ip,band)], Memi[data],
+ npix*blnum)
+ }
+
+ case TY_LONG:
+ call amovl (Meml[dptr], Meml[data+((blnum-1)*npix)], npix)
+ if (and(IP_FLIP(ip),FLIP_Y) == FLIP_Y) {
+ data = imps3l (im, 1, npix,
+ max(1,(lnum-IP_SZBUF(ip)+1)+IP_SZBUF(ip)-1),
+ max(1,lnum+min(nldone,IP_SZBUF(ip))-1),
+ band, band)
+ call amovl (Meml[BUFFER(ip,band)+(blnum-1)*npix],
+ Meml[data], npix*(IP_SZBUF(ip)-blnum+1))
+ } else {
+ data = imps3l (im, 1, npix,
+ min(IP_AXLEN(ip,2),(lnum-blnum+1)),
+ min(IP_AXLEN(ip,2),lnum),
+ band, band)
+ call amovl (Meml[BUFFER(ip,band)], Meml[data],
+ npix*blnum)
+ }
+
+ case TY_REAL:
+ call amovr (Memr[dptr], Memr[data+((blnum-1)*npix)], npix)
+ if (and(IP_FLIP(ip),FLIP_Y) == FLIP_Y) {
+ data = imps3r (im, 1, npix,
+ max(1,(lnum-IP_SZBUF(ip)+1)+IP_SZBUF(ip)-1),
+ max(1,lnum+min(nldone,IP_SZBUF(ip))-1),
+ band, band)
+ call amovr (Memr[BUFFER(ip,band)+(blnum-1)*npix],
+ Memr[data], npix*(IP_SZBUF(ip)-blnum+1))
+ } else {
+ data = imps3r (im, 1, npix,
+ min(IP_AXLEN(ip,2),(lnum-blnum+1)),
+ min(IP_AXLEN(ip,2),lnum),
+ band, band)
+ call amovr (Memr[BUFFER(ip,band)], Memr[data],
+ npix*blnum)
+ }
+
+ case TY_DOUBLE:
+ call amovd (Memd[dptr], Memd[data+((blnum-1)*npix)], npix)
+ if (and(IP_FLIP(ip),FLIP_Y) == FLIP_Y) {
+ data = imps3d (im, 1, npix,
+ max(1,(lnum-IP_SZBUF(ip)+1)+IP_SZBUF(ip)-1),
+ max(1,lnum+min(nldone,IP_SZBUF(ip))-1),
+ band, band)
+ call amovd (Memd[BUFFER(ip,band)+(blnum-1)*npix],
+ Memd[data], npix*(IP_SZBUF(ip)-blnum+1))
+ } else {
+ data = imps3d (im, 1, npix,
+ min(IP_AXLEN(ip,2),(lnum-blnum+1)),
+ min(IP_AXLEN(ip,2),lnum),
+ band, band)
+ call amovd (Memd[BUFFER(ip,band)], Memd[data],
+ npix*blnum)
+ }
+
+ }
+ if (band == IP_NBANDS(ip)) {
+ nldone = 1
+ blnum = 0
+ }
+ }
+
+ if (IP_OUTTYPE(ip) != O_TYPE(out))
+ call mfree (optr, type)
+ call sfree (sp)
+end
+
+
+# IP_UPKPIX -- Unpack a line of pixel-interleaved pixels to the separate
+# pixtype operand arrays.
+
+procedure ip_upkpix (ip, ptr, npix)
+
+pointer ip #i task struct pointer
+pointer ptr #i pointer to pixels
+int npix #i number of pixels in line
+
+pointer op[IM_MAXDIM]
+int i, j, np, optype[IM_MAXDIM]
+
+int ip_ptype()
+
+begin
+ np = IP_NPIXT(ip)
+ do j = 1, np {
+ op[j] = PTYPE(ip,j)
+ optype[j] = ip_ptype (IO_TYPE(op[j]),IO_NBYTES(op[j]))
+ }
+
+ do j = 1, np {
+
+ do i = 0, npix-1 {
+ switch (optype[j]) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ Mems[IO_DATA(op[j])+i] = Mems[ptr+(i*np+j)-1]
+
+ case TY_INT:
+ Memi[IO_DATA(op[j])+i] = Memi[ptr+(i*np+j)-1]
+
+ case TY_LONG:
+ Meml[IO_DATA(op[j])+i] = Meml[ptr+(i*np+j)-1]
+
+ case TY_REAL:
+ Memr[IO_DATA(op[j])+i] = Memr[ptr+(i*np+j)-1]
+
+ case TY_DOUBLE:
+ Memd[IO_DATA(op[j])+i] = Memd[ptr+(i*np+j)-1]
+
+ }
+ }
+ }
+end
+
+
+# IP_FIX_PIXTYPE -- Create the pixtype operands for 3-D band or line-
+# interleaved files. These weren't allocated at first since the pixtype
+# parameter or database field was atomic.
+
+procedure ip_fix_pixtype (ip)
+
+pointer ip #i task struct pointer
+
+pointer op, op1
+int i, nnp
+
+begin
+ if (DEBUG) {
+ call eprintf ("fix_pixtype: npixt=%d ndim=%d inter=%d\n")
+ call pargi(IP_NPIXT(ip)) ; call pargi(IP_NDIM(ip))
+ call pargi(IP_INTERLEAVE(ip)) ; call flush (STDERR)
+ }
+
+ # See if there's anything to be fixed.
+ if (IP_NDIM(ip) < 3 || IP_NDIM(ip) < IP_NPIXT(ip))
+ return
+ if (BAND_INTERLEAVED(ip) && (IP_NPIXT(ip) == IP_NDIM(ip)))
+ return
+ if (LINE_INTERLEAVED(ip) && (IP_NPIXT(ip) == IP_INTERLEAVE(ip)))
+ return
+
+ if (LINE_INTERLEAVED(ip))
+ nnp = IP_INTERLEAVE(ip)
+ else
+ #nnp = IP_NDIM(ip)
+ nnp = IP_AXLEN(ip,3)
+
+ # Make the new pixtype operands.
+ op1 = PTYPE(ip,1)
+ do i = 2, nnp {
+ call ip_alloc_operand (PTYPE(ip,i))
+ op = PTYPE(ip,i)
+ IO_TYPE(op) = IO_TYPE(op1)
+ IO_NBYTES(op) = IO_NBYTES(op1)
+ call sprintf (OP_TAG(op), SZ_TAG, "b%d")
+ call pargi (i)
+ }
+ IP_NPIXT(ip) = nnp
+
+ if (DEBUG) { call zzi_prstruct ("fix_pixtype", ip) }
+end
+
+
+# IP_FIX_OUTBANDS -- Create the outbands operands if none were specified in
+# the parameter file.
+
+procedure ip_fix_outbands (ip)
+
+pointer ip #i task struct pointer
+
+pointer sp, buf
+pointer im
+int i, nbands
+
+define SZ_OBSTR 2500
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_FNAME, TY_CHAR)
+
+ if (DEBUG) {
+ call eprintf ("fix_outbands: npixt=%d ndim=%d inter=%d\n")
+ call pargi(IP_NPIXT(ip)) ; call pargi(IP_NDIM(ip))
+ call pargi(IP_INTERLEAVE(ip)) ; call flush (STDERR)
+ }
+
+ # Free up the existing outbands operands.
+ nbands = IP_NBANDS(ip)
+ do i = 1, nbands
+ call ip_free_outbands (OBANDS(ip,i))
+
+ # Create an outbands parameter string according to the tags in the
+ # pixtype structure. This way we preserve any user-defined tags on
+ # output.
+ nbands = IP_NPIXT(ip)
+ call aclrc (Memc[buf], SZ_FNAME)
+ do i = 1, nbands {
+ call ip_alloc_outbands (OBANDS(ip,i))
+ call aclrc (Memc[buf], SZ_FNAME)
+ call sprintf (Memc[buf], SZ_FNAME, "b%d")
+ call pargi (i)
+ call strcpy (Memc[buf], O_EXPR(ip,i), SZ_EXPR)
+
+ # Load the operand struct.
+ call strcpy (Memc[buf], OP_TAG(O_OP(ip,i)), SZ_EXPR)
+ }
+ IP_NBANDS(ip) = nbands
+
+ # Fix the output image dimensions.
+ im = IP_IM(ip)
+ IM_LEN(im,3) = IP_AXLEN(ip,3)
+ if (IP_NBANDS(ip) > 1)
+ IM_NDIM(im) = 3
+ else
+ IM_NDIM(im) = IP_NDIM(ip)
+
+ call sfree (sp)
+
+ if (DEBUG) { call zzi_prstruct ("fix_outbands", ip) }
+end
+
+
+# IP_CHTYPE - Change the expression operand vector to the output datatype.
+# We allocate and return a pointer to the correct type to the converted
+# pixels, this pointer must be freed later on.
+
+pointer procedure ip_chtype (op, type)
+
+pointer op #i evvexpr operand pointer
+int type #i new type of pointer
+
+pointer out, coerce()
+
+begin
+ # Allocate the pointer and coerce it so the routine works.
+ if (type == TY_UBYTE || type == TY_CHAR)
+ call calloc (out, O_LEN(op), TY_CHAR)
+ else {
+ call calloc (out, O_LEN(op), type)
+ out = coerce (out, type, TY_CHAR)
+ }
+
+ # Change the pixel type.
+ switch (O_TYPE(op)) {
+ case TY_CHAR:
+ call achtc (Memc[O_VALP(op)], Memc[out], O_LEN(op), type)
+ case TY_SHORT:
+ call achts (Mems[O_VALP(op)], Memc[out], O_LEN(op), type)
+ case TY_INT:
+ call achti (Memi[O_VALP(op)], Memc[out], O_LEN(op), type)
+ case TY_LONG:
+ call achtl (Meml[O_VALP(op)], Memc[out], O_LEN(op), type)
+ case TY_REAL:
+ call achtr (Memr[O_VALP(op)], Memc[out], O_LEN(op), type)
+ case TY_DOUBLE:
+ call achtd (Memd[O_VALP(op)], Memc[out], O_LEN(op), type)
+ default:
+ call error (0, "Invalid output type requested.")
+ }
+
+ out = coerce (out, TY_CHAR, type)
+ return (out)
+end
+
+
+define NTYPES 6
+define NBITPIX 4
+
+# IP_PTYPE -- For a given pixtype parameter return the corresponding IRAF
+# data type.
+
+int procedure ip_ptype (type, nbytes)
+
+int type #i pixel type
+int nbytes #i number of bytes
+
+int i, pt, pb, ptype
+int tindex[NTYPES], bindex[NBITPIX], ttbl[NTYPES*NBITPIX]
+
+data tindex /PT_BYTE, PT_UINT, PT_INT, PT_IEEE, PT_NATIVE, PT_SKIP/
+data bindex /1, 2, 4, 8/
+
+data (ttbl(i), i= 1, 4) /TY_UBYTE, TY_USHORT, TY_INT, 0/ # B
+data (ttbl(i), i= 5, 8) /TY_UBYTE, TY_USHORT, 0, 0/ # U
+data (ttbl(i), i= 9,12) /TY_UBYTE, TY_SHORT, TY_INT, 0/ # I
+data (ttbl(i), i=13,16) / 0, 0, TY_REAL, TY_DOUBLE/ # R
+data (ttbl(i), i=17,20) / 0, 0, TY_REAL, TY_DOUBLE/ # N
+data (ttbl(i), i=21,24) /TY_UBYTE, TY_USHORT, TY_REAL, TY_DOUBLE/ # X
+
+begin
+ if (type == 0 || nbytes == 0) # uninitialized values
+ return (0)
+
+ pt = NTYPES
+ do i = 1, NTYPES {
+ if (tindex[i] == type)
+ pt = i
+ }
+ pb = NBITPIX
+ do i = 1, NBITPIX {
+ if (bindex[i] == nbytes)
+ pb = i
+ }
+
+ ptype = ttbl[(pt-1)*NBITPIX+pb]
+ if (ptype == 0)
+ call error (0, "Invalid pixtype specified.")
+ else
+ return (ptype)
+end
+
+
+# IP_PSTAT - Print information about the progress we're making.
+
+procedure ip_pstat (ip, row, percent)
+
+pointer ip #i task struct pointer
+int row #u current row
+int percent #u percent completed
+
+begin
+ # Print percent done if being verbose
+ if (row * 100 / IP_AXLEN(ip,2) >= percent + 10) {
+ percent = percent + 10
+ call eprintf (" Status: %2d%% complete\r")
+ call pargi (percent)
+ call flush (STDERR)
+ }
+end
diff --git a/pkg/dataio/import/generic/mkpkg b/pkg/dataio/import/generic/mkpkg
new file mode 100644
index 00000000..9e8721db
--- /dev/null
+++ b/pkg/dataio/import/generic/mkpkg
@@ -0,0 +1,15 @@
+# Compile the generic sources.
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+libpkg.a:
+ ipdb.x ../import.h ../ipfcn.h \
+ <error.h> <evvexpr.h> <imhdr.h> <mach.h>
+ ipfio.x ../import.h <fset.h> <mach.h>
+ ipobands.x ../import.h ../ipfcn.h <error.h> <evvexpr.h> \
+ <fset.h> <mach.h>
+ ipproc.x ../import.h <evvexpr.h> <imhdr.h> <mach.h>
+ ;
diff --git a/pkg/dataio/import/images.dat b/pkg/dataio/import/images.dat
new file mode 100644
index 00000000..dd8123ce
--- /dev/null
+++ b/pkg/dataio/import/images.dat
@@ -0,0 +1,433 @@
+# IMAGES.DAT -- Database of known formats recognized by the IMPORT task.
+#
+# Each record of the database is of the form:
+#
+# <format_name>:
+# <alias>:
+# <alias>:
+# keyword = <expr>
+# keyword = <expr>
+# ...and so on
+#
+# A database record begins with the format name at the beginning of a line.
+# Whitespace at the beginning of a line is considered the continuation of a
+# previous line. Comments may be inserted in the database using the normal '#'
+# character, the remainder of the line is considered a comment. Blank lines
+# and comments are ignored, a record ends at the next line with a format name
+# at the beginning of the line.
+#
+# The format_name field is a string identifying each entry in the
+# database, an alias may also be given to identify the same field if known
+# by another name. Supported keywords include:
+#
+# image_id - A boolean expression identifying the image type, either
+# using a literal string or one of the provided functions
+# id_string - Verbose name of file format
+# bswap - Is file byte-swapped? (See Below)
+# dims - A whitespace/comma delimited string of image dimension
+# pixtype - Pixel type, size [and tag], may be a composite
+# interleave - Describes how pixels are stored
+# hskip - # of bytes of header info to skip
+# tskip - # of bytes of trailing info to skip at end of file
+# bskip - # of bytes of info to skip between image bands
+# lskip - # of bytes of info to skip at the front of each line
+# lpad - # of bytes of info to skip at the end of each line
+# yflip - Image is flipped relative to normal IRAF orientation
+# comment - (Multiple) informational comment string to be printed,
+# e.g. to warn the user about the pixel ordering.
+# error - A condition that would cause a file read error, returns
+# a string with the error message, otherwise NULL
+#
+# Expressions include not only functions supported by the system expression
+# evaluator but also special functions particular to the IMPORT task. The
+# user is referred to the IMPORT help page for more details on the database
+# functions.
+#
+# Expressions may also contain *previously defined* database fields, so for
+# instance the 'hskip' keyword can be computed in an expression using the
+# value of the 'pixtype' keyword. Additionally, several special operands are
+# also supported and may be used in expressions:
+#
+# $FSIZE - the size in bytes of the binary file
+# $FNAME - the name of the binary file
+
+
+
+avs: # AVS X image file
+mbfx:
+mbfavs:
+x:
+ image_id = ($FSIZE - (geti4(1) * geti4(5) * 4) == 8)
+ id_string = "AVS X Image Format file"
+ dims = (str(geti4(1)) // "," // str(geti4(5))) // ",4"
+ pixtype = "x1,b1,b1,b1"
+ hskip = 8
+ yflip = 1
+ comment = "Note: The first band of this image is an alpha channel."
+
+
+clementine: # CLEMENTINE mission image
+pds3:
+ image_id = (getstr(1,23) == "PDS_VERSION_ID = PDS3")
+ id_string = "CLEMENTINE 1 PDS3 image data file"
+ pixtype = "b1"
+ hskip = int(locate(1,"OBJECT = IMAGE\r\n")+16)
+ bskip = int(locate(hskip,"LINE_SAMPLES"))
+ lskip = int(locate(hskip,"LINES"))
+# dims = ((str(ctoi((locate(hskip,"LINE_SAMPLES")+17)))) // "," //
+# (str(ctoi((locate(hskip,"LINES")+17)))) )
+ dims = ((str(ctoi((locate(bskip,"=")+1)))) // "," //
+ (str(ctoi((locate(lskip,"=")+1)))) )
+ hskip = (ctoi(locate(1,"^IMAGE ")+18))
+ bskip = 0
+ lskip = 0
+ yflip = 0
+
+
+export: # EXPORT task output format
+ image_id = (getstr(1,15) == "format = EXPORT")
+ id_string = "IRAF EXPORT file (with header)"
+ bswap = (getstr(locate(1,"bswap")+9,locate(1,"bswap")+11) == "no")
+ hskip = ctoi(locate(1,"hdrsize =")+10)
+ pixtype = (getstr(locate(1,"datatype = '")+12,2))
+ dims = ((ctoi(locate(1,"nbands =")+8) > 1) ?
+ (str(ctoi(locate(1,"ncols = ")+8)) // "," //
+ str(ctoi(locate(1,"nrows = ")+8)) // "," //
+ str(ctoi(locate(1,"nbands = ")+9)))
+ : (str(ctoi(locate(1,"ncols = ")+8)) // "," //
+ str(ctoi(locate(1,"nrows = ")+8))))
+ interleave = ctoi(locate(1,"interleave =")+13)
+
+
+fits: # Uhh, use RFITS for this
+ bswap = parameter ("bswap")
+ image_id = (getstr(1,9) == "SIMPLE =")
+ id_string = "FITS Format image"
+ hskip = ( int (locate(1,"END ") / 2800) ) * 2880
+ pixtype = ( str (ctoi((locate(1,"BITPIX")+10))) )
+ pixtype = ((pixtype == "8" ? "b1" :
+ (pixtype == "16" ? "i2" :
+ (pixtype == "32" ? "i4" :
+ (pixtype == "-32" ? "r4" :
+ (pixtype == "-64" ? "r8" : "0"))))))
+ dims = ((ctoi(locate(1,"NAXIS ")+10) == 3) ?
+ (str(ctoi(locate(1,"NAXIS1")+10)) // "," //
+ str(ctoi(locate(1,"NAXIS2")+10)) // "," //
+ str(ctoi(locate(1,"NAXIS3")+10)))
+ : (str(ctoi(locate(1,"NAXIS1")+10)) // "," //
+ str(ctoi(locate(1,"NAXIS2")+10))))
+
+
+gif: # CompuServe's GIF format
+giff:
+ image_id = ( (getstr(1,6) == "GIF87a") || (getstr(1,6) == "GIF89a") )
+ id_string = "CompuServe GIF Format File"
+ dims = (str((getb(7)+(256*getb(8)))) //","// str((getb(9)+(256*getb(10)))))
+ pixtype = "u1"
+ hskip = 22
+ yflip = 1
+ comment = "Note: Colormap information will automatically be applied."
+
+
+oif: # An IRAF OIF pixel file
+imh:
+iraf:
+ bswap = (geti2(1) == 26880 && # bswap("impix" in SPP chars)
+ geti2(3) == 27904 &&
+ geti2(5) == 28672 &&
+ geti2(7) == 26880 &&
+ geti2(9) == 30720)
+ image_id = (geti2(1) == 105 && # "impix" in SPP chars
+ geti2(3) == 109 &&
+ geti2(5) == 112 &&
+ geti2(7) == 105 &&
+ geti2(9) == 120)
+ id_string = "IRAF OIF image pixel file"
+ dims = ((geti2(23) == 3) ?
+ (str(geti2(27)) //","// str(geti2(31)) //","// str(geti2(35)))
+ : (str(geti2(27)) //","// str(geti2(31))) )
+ pixtype = ((geti2(17) == 3 ? "i2" :
+ (geti2(17) == 4 ? "i4" :
+ (geti2(17) == 5 ? "i4" :
+ (geti2(17) == 6 ? "n4" :
+ (geti2(17) == 7 ? "n8" : ""))))) )
+ hskip = 1024
+ lpad = (geti2(55) - geti2(27))
+ lpad = (lpad * ((geti2(17) == 3 ? (2) :
+ (geti2(17) == 4 ? (4) :
+ (geti2(17) == 5 ? (4) :
+ (geti2(17) == 6 ? (4) :
+ (geti2(17) == 7 ? (8) : (1))))))) )
+ error = (geti2(23) > 3) ? "Maximum of 3 dimensions supported." : "okay"
+ error = ((geti2(17) > 7) || (geti2(17) < 3)) ?
+ "Image data type not supported." : "okay"
+
+
+mcidas: # Unidata McIDAS file
+ image_id = (geti4(5) == 4)
+ id_string = "McIDAS"
+ dims = (str(geti4(37)) // "," // str(geti4(33)))
+ pixtype = "b1"
+ hskip = geti4(133)
+ lskip = geti4(57)
+ yflip = 1
+
+
+miff: # ImageMagick MIFF format
+mif:
+ image_id = (locate(1,"id=ImageMagick") < locate (1,":\n"))
+ id_string = "ImageMagick MIFF format file"
+ hskip = ((locate(1,":\n") + 1) + (ctoi(locate(1,"colors=")+7) * 3) + 1)
+ dims = (str(ctoi(locate(1,"columns=")+8)) // "," //
+ str(ctoi(locate(1,"rows=")+5)) )
+ yflip = 1
+ pixtype = (getstr(locate(1,"class=")+6,6) == "Direct" ? "b1,b1,b1" :
+ ((ctoi(locate(1,"colors=")+7) > 256) ? "b2" : "b1"))
+ error = locate(1,"compression") > 1 ?
+ "Compressed files not supported" : "okay"
+ error = ctoi(locate(1,"colors=")+7) > 256 ?
+ "Too many entries in colormap" : "okay"
+ comment = "Note: Colormaps will not be applied to image."
+
+
+pgm: # PBMPlus PGM format
+rpgm:
+ image_id = (getstr(1,2) == "P5" || getstr(1,2) == "P2")
+ id_string = "PBMPlus PGM format file"
+ pixtype = "b1"
+ hskip = ((str(getstr(line(2),1)) != "#") ? # see if there's a comment
+ (int(line(4) - 1))
+ : (int(line(5) - 1)) )
+ dims = ((str(getstr(line(2),1)) != "#") ?
+ (str(ctoi(line(2))) // "," // str(ctoi(locate(line(2)," "))))
+ : (str(ctoi(line(3))) // "," // str(ctoi(locate(line(3)," ")))) )
+ yflip = 1
+ error = getstr(1,2) == "5P" ? "File is byte-swapped" : "okay"
+ error = getstr(1,2) == "P2" ? "Only raw PGM files are supported." : "okay"
+
+
+ppm: # PBMPlus PPM format
+pnm:
+rppm:
+ image_id = (getstr(1,2) == "P6" || getstr(1,2) == "P3")
+ id_string = "PBMPlus PPM format file"
+ pixtype = "b1,b1,b1"
+ hskip = ((str(getstr(line(2),1)) != "#") ? # see if there's a comment
+ (int(line(4) - 1))
+ : (int(line(5) - 1)) )
+ dims = ((str(getstr(line(2),1)) != "#") ?
+ (str(ctoi(line(2))) // "," // str(ctoi(locate(line(2)," "))))
+ : (str(ctoi(line(3))) // "," // str(ctoi(locate(line(3)," ")))) )
+ dims = dims // ",3"
+ yflip = 1
+ error = getstr(1,2) == "6P" ? "File is byte-swapped" : "okay"
+ error = getstr(1,2) == "P3" ? "Only raw PGM files are supported." : "okay"
+
+
+rgb: # SGI RGB format image
+iris:
+sgi:
+ bswap = (getu(1) == bswap(0732b))
+ image_id = (getu(1) == 0732b)
+ id_string = "SGI RGB Image file"
+ dims = ((geti2(5) == 3) ?
+ (str(geti2(7)) // "," // str(geti2(9)) // "," // str(geti2(11)))
+ : (str(geti2(7)) // "," // str(geti2(9))) )
+ pixtype = "b1"
+ hskip = 512
+ interleave = 0
+ error = (geti2(3) == 3) ? "Colormap files not supported" : "okay"
+ error = ((geti2(3) != 0) && (geti2(3) != 1)) ?
+ "Format of RGB file not supported" : "okay"
+ error = (geti2(3) == 257) ? "RLE compressed files not supported" : "okay"
+
+
+sunras: # Sun rasterfile
+ras:
+ bswap = (geti4(1) == bswap(59a66a95x))
+ image_id = (geti4(1) == 59a66a95x || bswap)
+ id_string = "Sun Rasterfile"
+ dims = (str(geti4(5)) // "," // str(geti4(9)) //
+ ((geti4(13) > 8) ? ("," // str(3)) : " ") )
+ pixtype = ((geti4(13) == 8 ? "b1" :
+ (geti4(13) == 24 ? "b1,b1,b1" :
+ (geti4(13) == 32 ? "x1,b1,b1,b1" : "x1,b1,b1,b1") )) )
+ interleave = 0
+ hskip = (32 + geti4(29))
+ yflip = 1
+ comment = "Note: Colormaps will automatically be applied to 8-bit images."
+ error = geti4(13) == 1 ? "1-bit rasters not supported." : "okay"
+
+
+iff: # Sun TAAC Image File Format
+taac:
+vff:
+suniff:
+ image_id = (getstr(1,4) == "ncaa")
+ id_string = "Sun TAAC Image File Format"
+ dims = (str(ctoi(locate(1,"size=")+5)) // "," //
+ str(ctoi(locate((locate(1,"size=")+5)," "))) )
+ dims = ((ctoi((locate(1,"bands=")+6)) == 3) ? (dims // ",3") : dims )
+ hskip = $FSIZE - (ctoi(locate(1,"size=")+5) *
+ ctoi(locate((locate(1,"size=")+5)," ")) *
+ ctoi((locate(1,"bands=")+6)) )
+ pixtype = ((ctoi((locate(1,"bands=")+6)) == 3) ? "b1,b1,b1" : "b1" )
+ yflip = 1
+ comment = "Note: Colormaps will not be applied to 8-bit images."
+
+
+vicar: # VICAR format file
+ bswap = ( msb_host() && (getstr((locate(1,"INTFMT=")+8),3) == "LOW") )
+ image_id = (getstr(1,8) == "LBLSIZE=")
+ id_string = "VICAR format image data file"
+ hskip = (ctoi((locate(1,"LBLSIZE=")+8)) +
+ (ctoi((locate(1,"NLB=")+4)) * ctoi((locate(1,"RECSIZE=")+8))))
+ lskip = (ctoi((locate(1,"NBB=")+4)))
+ interleave = (((getstr((locate(1,"ORG=")+5),3))) == "BSQ" ? 0 :
+ ((getstr((locate(1,"ORG=")+5),3)) == "BIL" ?
+ ctoi(locate(1,"NB=")+3) : 999) )
+ pixtype = (getstr((locate(1,"FORMAT=")+8),4))
+ pixtype = ((pixtype == "BYTE" ? "b1" :
+ (pixtype == "HALF" ? "i2" :
+ (pixtype == "FULL" ? "i4" :
+ (pixtype == "REAL" ? "r4" :
+ (pixtype == "DOUB" ? "r8" : "0"))))))
+ pixtype = (((interleave) != 999) ? pixtype :
+ ((ctoi(locate(1,"DIM=")+5) == 2) ?
+ pixtype // "," // pixtype :
+ ((ctoi(locate(1,"DIM=")+5) == 3) ?
+ pixtype // "," // pixtype // "," // pixtype :
+ (pixtype) )) )
+ dims = (((ctoi(locate(1,"DIM=")+4)==3) && (ctoi(locate(1,"N3=")+3)!=1)) ?
+ (str(ctoi(locate(1,"N1=")+3)) // "," //
+ str(ctoi(locate(1,"N2=")+3)) // "," //
+ str(ctoi(locate(1,"N3=")+3)))
+ : (str(ctoi(locate(1,"N1=")+3)) // "," //
+ str(ctoi(locate(1,"N2=")+3))))
+ yflip = 1
+ error = ((getstr((locate(1,"TYPE=")+6),5) != "IMAGE") ?
+ "Not a VICAR image file." : "okay")
+ error = ((getstr((locate(1,"FORMAT=")+8),4) == "COMP") ?
+ "Complex image data not supported" : "okay")
+
+
+x10: # X10 Window Dump file
+x10wd:
+ image_id = (geti4(5) == 6)
+ id_string = "X10 Window Dump file"
+ hskip = ( geti4(1) + (10 * geti2(39)) )
+ pixtype = "b1"
+ dims = (str(geti4(21)) // "," // str(geti4(25)))
+ comment = "Note: Colormaps will not be applied to image."
+
+
+xwd: # X11 Window Dump file
+x11:
+x11wd:
+ #bswap = ( msb_host() && (geti4(29) == 0) )
+ image_id = (geti4(5) == 7)
+ id_string = "X11 Window Dump file"
+ dims = (str(geti4(17)) // "," // str(geti4(21)))
+ dims = ( (geti4(45) == 24) ? str (dims // ",3") : dims ) # add dims
+ dims = ( (geti4(45) == 32) ? str (dims // ",4") : dims ) # add dims
+ hskip = ( geti4(1) + (12 * geti4(73)) )
+ # On a 64-bit machine the colormap struct is 16 bytes long instead of
+ # 12, see if we have one of these files and pad the header.
+ hskip = ( ((geti4(17)*geti4(21)*(geti4(45)/8)) + hskip) < ($FSIZE-1024) ?
+ (hskip + (4*geti4(73))) : hskip)
+ lpad = ( geti4(49) - (geti4(17) * (geti4(45) / 8)) )
+ pixtype = ( (geti4(45) == 8) ? "b1" :
+ (geti4(45) == 24) ? "b1,b1,b1" :
+ (geti4(45) == 32) ? "x1,b1,b1,b1" : "x1,b1,b1,b1" )
+ yflip = 1
+
+
+
+#########################################################################
+# #
+# The following database entries are not supported for conversion but #
+# are provided for file identification purposes. #
+# #
+#########################################################################
+
+
+cmuwmraster: # CMU Window Manager Raster
+ bswap = (geti4(1) == bswap(00F10040BBx))
+ image_id = (geti4(1) == 00F10040BBx || bswap)
+ id_string = "CMU Window manager Raster file (ID only)"
+ dims = (str(geti4(5)) // "," // str(geti4(9)) // "," // str(geti2(11)))
+ error = (1 == 1) ? "CMU raster supported for file identification only." :
+ "okay"
+
+
+fbm: # Fuzzy Bitmap Format file
+ image_id = (getstr(1,7) == "%bitmap")
+ id_string = "Fuzzy Bitmap Format file (ID only)"
+ dims = (str(ctoi(getstr(17,8))) // "," // str(ctoi(getstr(9,8))))
+ error = (1 == 1) ? "FBM supported for file identification only." :
+ "okay"
+
+
+hdf: # NCSA Hierarchical Data File
+df:
+ncsa:
+ bswap = ( lsb_host() )
+ image_id = (geti4(1) == 0e031301x)
+ id_string = "NCSA Hierarchical Data File (ID only)"
+ dims = (str(geti2(822)) // "," // str(geti2(826)))
+ error = (1 == 1) ? "NCSA HDF supported for file identification only." :
+ "okay"
+
+msp: # Microsoft Paint Bitmap
+ bswap = (geti2(1) == bswap(01800x) || geti2(1) == bswap(0694Cx))
+ image_id = ((geti2(1) == 01800x && geti2(3) == 04D6Ex) ||
+ (geti2(1) == 0694Cx && geti2(3) == 0536Ex))
+ id_string = "Microsoft Paint Bitmap (ID only)"
+ dims = (str(geti2(5)) // "," // str(geti2(7)))
+ error = (1 == 1) ? "MSP supported for file identification only." :
+ "okay"
+
+pcx: # PC Paintbrush File Format
+dcx:
+pcc:
+ image_id = (getb(1) == 010x)
+ id_string = "PC Paintbrush File (ID only)"
+ dims = (str(geti2(9) - geti2(5) + 1) // "," //
+ str(geti2(11) - geti2(7) + 1))
+ error = (1 == 1) ? "PC Paintbrush supported for file identification only." :
+ "okay"
+
+pic: # Pictor PC Paint
+clp:
+ bswap = (geti2(1) == bswap(01234x))
+ image_id = (geti2(1) == 01234x)
+ id_string = "Pictor PC Paint bitmap (ID only)"
+ dims = (str(geti2(3)) // "," // str(geti2(5)))
+ error = (1 == 1) ? "PC Paint supported for file identification only." :
+ "okay"
+
+ps: # Postscript file
+postscript:
+ image_id = (getstr(1,2) == "%!")
+ id_string = "Postscript file (ID only)"
+ error = (1 == 1) ? "PS supported for file identification only." :
+ "okay"
+
+
+rle: # Utah Raster Toolkit file
+utah:
+ image_id = (getb(1) == 52x || getb(1) == 00CCx)
+ id_string = "Utah Raster Toolkit Format file (ID only)"
+ error = (1 == 1) ? "RLE supported for file identification only." :
+ "okay"
+
+
+tif: # TIFF format file
+tiff:
+ bswap = (geti2(1) == bswap(4949x) || geti2(1) == bswap(4D4Dx))
+ image_id = ((geti2(1) == 4D4Dx && geti2(3) == 002Ax) ||
+ (geti2(1) == 4949x && geti2(3) == 2A00x))
+ id_string = "TIFF Format file (ID only)"
+ error = (1 == 1) ? "TIFF supported for file identification only." :
+ "okay"
+
diff --git a/pkg/dataio/import/import.h b/pkg/dataio/import/import.h
new file mode 100644
index 00000000..6d80020a
--- /dev/null
+++ b/pkg/dataio/import/import.h
@@ -0,0 +1,132 @@
+# IMPORT.H - Data structure definition file for the IMPORT task.
+
+define SZ_IMPSTRUCT 40 # size of the import structure
+define SZ_EXPR (20*SZ_LINE) # max size of an expression
+define SZ_COMMENT 1024 # size of a database format comment
+define LEN_UA 20000 # minimum user header length
+define MAX_OPERANDS 1024
+
+# Input format parameters.
+define IP_INTERLEAVE Memi[$1] # type of data interleaving
+define IP_HSKIP Memi[$1+1] # bytes to skip before data
+define IP_TSKIP Memi[$1+2] # bytes to skip after data
+define IP_BSKIP Memi[$1+3] # bytes between image bands
+define IP_LSKIP Memi[$1+4] # bytes to skip at front of line
+define IP_LPAD Memi[$1+5] # bytes to skip at end of line
+define IP_SWAP Memi[$1+6] # type of byte swapping
+define IP_NPIXT Memi[$1+7] # number of pixtypes
+define IP_PIXTYPE Memi[$1+8] # pixtype ptr to operands
+define IP_NDIM Memi[$1+9] # number of input axes
+define IP_AXLEN Memi[($1+10)+$2-1] # input axis dimension
+
+# Output parameters.
+define IP_OUTPUT Memi[$1+20] # type of output generated
+define IP_OUTTYPE Memi[$1+21] # output pixel type
+define IP_NBANDS Memi[$1+22] # no. of outbands expr string
+define IP_OUTBANDS Memi[$1+23] # outbands expr string (ptr)
+define IP_IMHEADER Memi[$1+24] # file w/ header info (ptr)
+define IP_VERBOSE Memi[$1+25] # verbose output flag
+
+define IP_FORMAT Memi[$1+26] # format param
+define IP_BLTIN Memi[$1+27] # format is a 'builtin'
+define IP_FCODE Memi[$1+28] # builtin format code
+define IP_FSYM Memi[$1+29] # symtab pointer to db record
+define IP_IM Memi[$1+30] # output image pointer
+define IP_FD Memi[$1+31] # binary file pointer
+define IP_OFFSET Memi[$1+32] # binary file offset
+define IP_FLIP Memi[$1+33] # output image orientation flag
+define IP_COMPTR Memi[$1+34] # comment block pointer
+
+define IP_BUFPTR Memi[$1+35] # array of image buffers (ptr)
+define IP_NPTRS Memi[$1+36] # number of image buffer
+define IP_SZBUF Memi[$1+37] # size of image buffer (lines)
+
+define IP_CMAP Memi[$1+38] # image colormap (ptr)
+define IP_USE_CMAP Memi[$1+39] # use the image colormap?
+
+# Useful Macros
+define PTYPE Memi[IP_PIXTYPE($1)+$2-1]
+define OBANDS Memi[IP_OUTBANDS($1)+$2-1]
+define COMMENT Memc[IP_COMPTR($1)]
+define BUFFER Memi[IP_BUFPTR($1)+$2-1]
+
+
+#-----------------------------------------------------------------------------
+
+# Outbands structure
+define LEN_OUTBANDS 2
+define OB_EXPR Memi[$1] # expression string
+define OB_OP Memi[$1+1] # operand struct pointer
+define O_EXPR Memc[OB_EXPR(OBANDS($1,$2))]
+define O_OP OB_OP(OBANDS($1,$2))
+
+# Operand structure
+define SZ_TAG 15
+define LEN_OPERAND 6
+define IO_TAG Memi[$1] # operand tag name
+define IO_TYPE Memi[$1+1] # operand type
+define IO_NBYTES Memi[$1+2] # number of bytes
+define IO_NPIX Memi[$1+3] # number of pixels
+define IO_DATA Memi[$1+4] # line of pixels
+define OP_TAG Memc[IO_TAG($1)]
+
+
+# Format type flags
+define IP_NONE 1 # format derived from task params
+define IP_SENSE 2 # format divined from database
+define IP_NAME 3 # format derived from database
+define IP_BUILTIN 4 # format derived from database
+
+# Output type flags
+define IP_IMAGE 5 # generate an output image
+define IP_LIST 6 # list pixels (according to 'outbands')
+define IP_INFO 7 # print info about image format
+
+# Byte swapping flags
+define S_NONE 000B # swap nothing
+define S_ALL 001B # swap everything
+define S_I2 002B # swap short ints
+define S_I4 004B # swap long ints
+define SWAP_STR "|no|none|yes|i2|i4|"
+
+# Image flipping flags
+define FLIP_NONE 000B # don't flip the image
+define FLIP_X 001B # flip image in X
+define FLIP_Y 002B # flip image in Y
+
+# Pixtype pixel types
+define PT_BYTE 1 # byte data (no conversion)
+define PT_UINT 2 # unsigned integer
+define PT_INT 3 # signed integer
+define PT_IEEE 4 # ieee floating point
+define PT_NATIVE 5 # native floating point
+define PT_SKIP 6 # skip
+
+# Default task parameters.
+define DEF_SWAP S_NONE
+define DEF_INTERLEAVE 0
+define DEF_HSKIP 0
+define DEF_TSKIP 0
+define DEF_BSKIP 0
+define DEF_LSKIP 0
+define DEF_LPAD 0
+
+# Useful macros.
+define BAND_INTERLEAVED ((IP_NPIXT($1)==1)&&(IP_INTERLEAVE($1)==0))
+define LINE_INTERLEAVED ((IP_NPIXT($1)==1)&&(IP_INTERLEAVE($1)>1))
+define PIXEL_INTERLEAVED ((IP_NPIXT($1)>1)&&(IP_INTERLEAVE(ip)==0))
+
+# NTSC grayscale coefficients.
+define R_COEFF 0.299
+define G_COEFF 0.587
+define B_COEFF 0.114
+
+# Colormap definitions.
+define CMAP_SIZE 256 # Output colormap length
+define CMAP_MAX 255 # Maximum map value
+define CMAP Memc[$1+($2*CMAP_SIZE)+$3-1]
+
+define IP_RED 0
+define IP_GREEN 1
+define IP_BLUE 2
+
diff --git a/pkg/dataio/import/ipbuiltin.x b/pkg/dataio/import/ipbuiltin.x
new file mode 100644
index 00000000..e95719be
--- /dev/null
+++ b/pkg/dataio/import/ipbuiltin.x
@@ -0,0 +1,91 @@
+include "import.h"
+
+
+# Define the builtin format names. We also define the aliases in case the
+# user specifies one of these instead, the 'sensed' format name is the
+# proper name.
+
+define IP_BUILTINS "|gif|giff\
+ |sunras|ras\
+ |xwd|x11|"
+
+define IP_GIF 1 # CompuServe GIF format
+define IP_GIFF 2 # CompuServe GIF format
+define IP_SUNRAS 3 # Sun Rasterfile
+define IP_RAS 4 # Sun Rasterfile
+define IP_XWD 5 # X11 Window Dump
+define IP_X11 6 # X11 Window Dump
+
+
+
+# IP_PRBUILTIN -- Process a 'builtin' format.
+
+procedure ip_prbuiltin (ip, fname)
+
+pointer ip #i task struct pointer
+char fname[ARB] #i file name
+
+
+begin
+ # Branch off to the particular format.
+ switch (IP_FCODE(ip)) {
+ case IP_GIF, IP_GIFF:
+ call ip_gif (ip, fname, NO, NO)
+ case IP_SUNRAS, IP_RAS:
+ call ip_ras (ip, fname, NO, NO)
+ case IP_XWD, IP_X11:
+ call ip_xwd (ip, fname, NO, NO)
+ default:
+ return
+ }
+end
+
+
+# IP_BLTIN_INFO -- Process a 'builtin' format file information request. These
+# are done separately because in a builtin we can print information such as
+# colormap information, compression schemes, etc.
+
+procedure ip_bltin_info (ip, fname, verbose)
+
+pointer ip #i task struct pointer
+char fname[ARB] #i file name
+int verbose #i verbosity flag
+
+begin
+ # Branch off to the particular format.
+ switch (IP_FCODE(ip)) {
+ case IP_GIF, IP_GIFF:
+ call ip_gif (ip, fname, YES, verbose)
+ case IP_SUNRAS, IP_RAS:
+ call ip_ras (ip, fname, YES, verbose)
+ case IP_XWD, IP_X11:
+ call ip_xwd (ip, fname, YES, verbose)
+ default:
+ return
+ }
+end
+
+
+# IP_IS_BUILTIN -- See if this is a 'builtin' format.
+
+int procedure ip_is_builtin (format)
+
+char format[ARB] #i format to check
+
+int btoi(), strdic()
+
+begin
+ return (btoi(strdic(format,format,SZ_FNAME,IP_BUILTINS) != 0))
+end
+
+
+# IP_FCODE -- Get the format code for a builtin format.
+
+int procedure ip_fcode (format)
+
+char format[ARB] #i format to check
+int strdic()
+
+begin
+ return (strdic (format, format, SZ_FNAME, IP_BUILTINS))
+end
diff --git a/pkg/dataio/import/ipdb.gx b/pkg/dataio/import/ipdb.gx
new file mode 100644
index 00000000..9e4cb5c3
--- /dev/null
+++ b/pkg/dataio/import/ipdb.gx
@@ -0,0 +1,766 @@
+include <evvexpr.h>
+include <error.h>
+include <mach.h>
+include <imhdr.h>
+include "../import.h"
+include "../ipfcn.h"
+
+define DEBUG false
+
+
+# IP_EVAL_DBREC -- For each of the keywords defined in the database record,
+# evaluate the expression and load the task structure.
+
+procedure ip_eval_dbrec (ip)
+
+pointer ip #i task struct pointer
+
+int ival
+pointer sp, dims, pixtype, err
+pointer np, stp, sym
+
+pointer stname(), sthead(), stnext
+int or(), ip_dbgeti()
+bool streq()
+
+errchk ip_dbgeti()
+
+begin
+ call smark (sp)
+ call salloc (dims, SZ_EXPR, TY_CHAR)
+ call salloc (pixtype, SZ_EXPR, TY_CHAR)
+ call salloc (err, SZ_EXPR, TY_CHAR)
+ call aclrc (Memc[dims], SZ_EXPR)
+ call aclrc (Memc[pixtype], SZ_EXPR)
+ call aclrc (Memc[err], SZ_EXPR)
+
+ # Load the defaults.
+ call ip_load_defaults (ip)
+
+ # First thing we do is get the byte swap flag so the remaining
+ # fields will be interpreted correctly.
+ ifnoerr (ival = ip_dbgeti (ip, "bswap"))
+ IP_SWAP(ip) = ival
+
+ # Next, we handle 'interleave', 'dims' and 'pixtype' as a special case
+ # since for band- and line-interleaved files we may need to fix up the
+ # pixtype pointers.
+ ifnoerr (ival = ip_dbgeti (ip, "interleave"))
+ IP_INTERLEAVE(ip) = ival
+
+ ifnoerr (call ip_dbstr (ip, "dims", Memc[dims], SZ_EXPR))
+ call ip_do_dims (ip, Memc[dims])
+
+ ifnoerr (call ip_dbstr (ip, "pixtype", Memc[pixtype], SZ_EXPR)) {
+ if (Memc[pixtype] == '"')
+ call fdb_strip_quote (Memc[pixtype], Memc[pixtype], SZ_EXPR)
+ call ip_do_pixtype (ip, Memc[pixtype])
+ }
+
+ # Loop over every symbol in the table.
+ stp = IP_FSYM(ip)
+ for (sym=sthead(stp); sym != NULL; sym=stnext(stp,sym)) {
+ np = stname (stp, sym)
+
+ if (streq(Memc[np],"format") || # ignored or found already
+ streq(Memc[np],"alias") ||
+ streq(Memc[np],"image_id") ||
+ streq(Memc[np],"interleave") ||
+ streq(Memc[np],"dims") ||
+ streq(Memc[np],"pixtype") ||
+ streq(Memc[np],"id_string") ||
+ streq(Memc[np],"bswap")) {
+ next
+ } else if (streq(Memc[np],"hskip")) {
+ IP_HSKIP(ip) = ip_dbgeti (ip, "hskip")
+ } else if (streq(Memc[np],"tskip")) {
+ IP_TSKIP(ip) = ip_dbgeti (ip, "tskip")
+ } else if (streq(Memc[np],"bskip")) {
+ IP_BSKIP(ip) = ip_dbgeti (ip, "bskip")
+ } else if (streq(Memc[np],"lskip")) {
+ IP_LSKIP(ip) = ip_dbgeti (ip, "lskip")
+ } else if (streq(Memc[np],"lpad")) {
+ IP_LPAD(ip) = ip_dbgeti (ip, "lpad")
+ } else if (streq(Memc[np],"yflip")) {
+ if (ip_dbgeti (ip, "yflip") == YES)
+ IP_FLIP(ip) = or (IP_FLIP(ip), FLIP_Y)
+ } else if (streq(Memc[np],"error")) {
+ if (IP_OUTPUT(ip) != IP_INFO)
+ call ip_do_error (ip, Memc[P2C(sym)])
+ } else if (streq(Memc[np],"comment")) {
+ call fdb_strip_quote (Memc[P2C(sym)], Memc[P2C(sym)], SZ_LINE)
+ call ip_do_comment (ip, Memc[P2C(sym)])
+ } else {
+ call eprintf ("Warning: Unknown database keyword '%s'.\n")
+ call pargstr (Memc[np])
+ }
+ }
+
+ if (DEBUG) { call zzi_prstruct ("eval dbrec:", ip) }
+ call sfree (sp)
+end
+
+
+# IP_LOAD_DEFAULTS -- Load the default input parameters to the task structure.
+
+procedure ip_load_defaults (ip)
+
+pointer ip #i task struct pointer
+
+begin
+ IP_SWAP(ip) = DEF_SWAP # type of byte swapping
+ IP_INTERLEAVE(ip) = DEF_INTERLEAVE # type of data interleaving
+ IP_HSKIP(ip) = DEF_HSKIP # bytes to skip before data
+ IP_TSKIP(ip) = DEF_TSKIP # bytes to skip after data
+ IP_BSKIP(ip) = DEF_BSKIP # bytes between image bands
+ IP_LSKIP(ip) = DEF_LSKIP # bytes to skip at front of
+ IP_LPAD(ip) = DEF_LPAD # bytes to skip at end of
+
+ # zero image dimensions
+ for (IP_NDIM(ip)=IM_MAXDIM; IP_NDIM(ip) > 0; IP_NDIM(ip)=IP_NDIM(ip)-1)
+ IP_AXLEN(ip,IP_NDIM(ip)) = 0
+end
+
+
+# IP_DBFCN -- Called by evvexpr to execute format database special functions.
+
+procedure ip_dbfcn (ip, fcn, args, nargs, o)
+
+pointer ip #i task struct pointer
+char fcn[ARB] #i function to be executed
+pointer args[ARB] #i argument list
+int nargs #i number of arguments
+pointer o #o operand pointer
+
+pointer sp, buf, outstr
+int fd, func, v_nargs
+int i, len, nchar, ival, cur_offset, swap
+char ch
+short sval
+real rval
+double dval
+
+short ip_getb(), ip_gets()
+int strdic(), ip_line(), ip_locate(), ip_getu()
+int ctoi(), ctol(), ctor(), ctod(), ctocc(), ctowrd()
+int and(), strlen(), clgeti()
+long ip_getl()
+real ip_getr(), ip_getn()
+double ip_getd(), ip_getn8()
+bool strne(), streq()
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+ call salloc (outstr, SZ_LINE, TY_CHAR)
+ call aclrc (Memc[buf], SZ_LINE)
+ call aclrc (Memc[outstr], SZ_LINE)
+
+ # Lookup function in dictionary.
+ func = strdic (fcn, Memc[buf], SZ_LINE, DB_FUNCTIONS)
+ if (func > 0 && strne(fcn,Memc[buf]))
+ func = 0
+
+ # Abort if the function is not known.
+ if (func <= 0)
+ call xev_error1 ("unknown function `%s' called", fcn)
+
+
+ # Verify the correct number of arguments, negative value means a
+ # variable number of args, handle it in the evaluation.
+ switch (func) {
+ case CTOCC, CTOD, CTOI, CTOL, CTOR, CTOWRD:
+ v_nargs = -1
+
+ case GETSTR:
+ v_nargs = -1
+ case GETB, GETU, GETI, GETI2, GETI4, GETR, GETR4, GETR8,
+ GETN, GETN4, GETN8:
+ v_nargs = 1
+
+ case LOCATE:
+ v_nargs = -1
+ case LINE, SKIP:
+ v_nargs = 1
+
+ case BSWAP:
+ v_nargs = 1
+ case PARAMETER, DEFAULT:
+ v_nargs = 1
+ case SUBSTR:
+ v_nargs = 3
+ case STRIDX:
+ v_nargs = 2
+ case LSB_HOST, MSB_HOST:
+ v_nargs = 0
+ }
+ if (v_nargs > 0 && nargs != v_nargs)
+ call xev_error2 ("function `%s' requires %d arguments",
+ fcn, v_nargs)
+ else if (v_nargs < 0 && nargs < abs(v_nargs))
+ call xev_error2 ("function `%s' requires at least %d arguments",
+ fcn, abs(v_nargs))
+
+ fd = IP_FD(ip)
+ swap = IP_SWAP(ip)
+ cur_offset = IP_OFFSET(ip)
+
+ if (DEBUG) {
+ call eprintf ("cur_offset=%d nargs=%d func=%s swap=%d\n")
+ call pargi(cur_offset) ; call pargi(nargs)
+ call pargstr(fcn) ; call pargi (swap)
+ do i = 1, nargs
+ call zzi_pevop (args[i])
+ call eprintf ("init op => ") ; call zzi_pevop(o)
+
+ }
+
+ # Evaluate the function.
+ switch (func) {
+ case CTOCC: # run the fmtio equivalents of the argument
+ if (nargs == 1)
+ ch = ip_getb (fd, O_VALI(args[1]))
+ else
+ ch = ip_getb (fd, cur_offset)
+ len = ctocc (ch, Memc[outstr], SZ_FNAME) + 1
+ call ip_initop (o, len, TY_CHAR)
+ call aclrc (O_VALC(o), len)
+ call amovc (Memc[outstr], O_VALC(o), len)
+ cur_offset = cur_offset + 1
+ call ip_lseek (fd, cur_offset)
+
+ case CTOWRD:
+ if (nargs == 1)
+ call ip_gstr (fd, O_VALI(args[1]), SZ_FNAME, Memc[outstr])
+ else
+ call ip_gstr (fd, cur_offset, SZ_FNAME, Memc[outstr])
+ nchar = ctowrd (Memc[outstr], i, Memc[outstr], SZ_FNAME) + 1
+ call ip_initop (o, nchar, TY_CHAR)
+ call aclrc (O_VALC(o), nchar)
+ call amovc (Memc[outstr], O_VALC(o), nchar)
+ cur_offset = cur_offset + nchar + 1
+ call ip_lseek (fd, cur_offset)
+
+ case CTOI:
+ i = 1
+ if (nargs == 1) {
+ call ip_gstr (fd, O_VALI(args[i]), SZ_FNAME, Memc[outstr])
+ nchar = ctoi (Memc[outstr], i, ival)
+ cur_offset = cur_offset + nchar - 1
+ } else if (nargs == 2) {
+ call ip_gstr (fd, O_VALI(args[1]), O_VALI(args[2]),Memc[outstr])
+ nchar = ctoi (Memc[outstr], i, ival)
+ cur_offset = O_VALI(args[1]) + nchar - 1
+ }
+ call ip_lseek (fd, cur_offset)
+ O_TYPE(o) = TY_INT
+
+ case CTOL:
+ i = 1
+ if (nargs == 1) {
+ call ip_gstr (fd, O_VALI(args[i]), SZ_FNAME, Memc[outstr])
+ nchar = ctol (Memc[outstr], i, ival)
+ cur_offset = cur_offset + nchar - 1
+ } else if (nargs == 2) {
+ call ip_gstr (fd, O_VALI(args[1]), O_VALI(args[2]),Memc[outstr])
+ nchar = ctol (Memc[outstr], i, ival)
+ cur_offset = O_VALI(args[1]) + nchar - 1
+ }
+ call ip_lseek (fd, cur_offset)
+ O_TYPE(o) = TY_LONG
+
+ case CTOR:
+ i = 1
+ if (nargs == 1) {
+ call ip_gstr (fd, O_VALI(args[i]), SZ_FNAME, Memc[outstr])
+ nchar = ctor (Memc[outstr], i, rval)
+ cur_offset = cur_offset + nchar - 1
+ } else if (nargs == 2) {
+ call ip_gstr (fd, O_VALI(args[1]), O_VALI(args[2]),Memc[outstr])
+ nchar = ctor (Memc[outstr], i, rval)
+ cur_offset = O_VALI(args[1]) + nchar - 1
+ }
+ call ip_lseek (fd, cur_offset)
+ O_TYPE(o) = TY_REAL
+
+ case CTOD:
+ i = 1
+ if (nargs == 1) {
+ call ip_gstr (fd, O_VALI(args[i]), SZ_FNAME, Memc[outstr])
+ nchar = ctod (Memc[outstr], i, dval)
+ cur_offset = cur_offset + nchar - 1
+ } else if (nargs == 2) {
+ call ip_gstr (fd, O_VALI(args[1]), O_VALI(args[2]),Memc[outstr])
+ nchar = ctod (Memc[outstr], i, dval)
+ cur_offset = O_VALI(args[1]) + nchar - 1
+ }
+ call ip_lseek (fd, cur_offset)
+ O_TYPE(o) = TY_DOUBLE
+
+ case GETSTR:
+ if (nargs == 1) {
+ call ip_gstr (fd, cur_offset, O_VALI(args[1]), Memc[outstr])
+ cur_offset = cur_offset + O_VALI(args[1])
+ } else if (nargs == 2) {
+ call ip_gstr (fd, O_VALI(args[1]), O_VALI(args[2]),Memc[outstr])
+ cur_offset = O_VALI(args[1]) + O_VALI(args[2]) - 1
+ }
+ if (strlen(Memc[outstr]) == 0) {
+ len = strlen ("ERR") + 1
+ call ip_initop (o, len, TY_CHAR)
+ call aclrc (O_VALC(o), len)
+ call strcpy ("ERR", O_VALC(o), len-1)
+ } else {
+ len = strlen (Memc[outstr]) + 1
+ call ip_initop (o, len, TY_CHAR)
+ call aclrc (O_VALC(o), len)
+ call amovc (Memc[outstr], O_VALC(o), len-1)
+ }
+
+ case GETB:
+ if (nargs == 0) {
+ sval = ip_getb (fd, cur_offset)
+ cur_offset = cur_offset + SZB_CHAR
+ } else {
+ sval = ip_getb (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + SZB_CHAR
+ }
+ ival = sval
+ O_TYPE(o) = TY_INT
+
+ case GETU:
+ if (nargs == 0) {
+ sval = short (ip_getu (fd, cur_offset))
+ cur_offset = cur_offset + (SZB_CHAR * SZ_SHORT)
+ } else {
+ sval = short (ip_getu (fd, O_VALI(args[1])))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_SHORT)
+ }
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2)
+ call bswap2 (sval, 1, sval, 1, (SZ_SHORT*SZB_CHAR))
+ ival = sval
+ O_TYPE(o) = TY_INT
+
+ case GETI, GETI2:
+ if (nargs == 0) {
+ sval = ip_gets (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_SHORT)
+ } else {
+ sval = ip_gets (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_SHORT)
+ }
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2)
+ call bswap2 (sval, 1, sval, 1, (SZ_SHORT*SZB_CHAR))
+ ival = sval
+ O_TYPE(o) = TY_INT
+
+ case GETI4:
+ if (nargs == 0) {
+ ival = ip_getl (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_LONG)
+ } else {
+ ival = ip_getl (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_LONG)
+ }
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I4)
+ call bswap4 (ival, 1, ival, 1, (SZ_INT32*SZB_CHAR))
+ O_TYPE(o) = TY_INT
+
+ case GETR, GETR4:
+ if (nargs == 0) {
+ rval = ip_getr (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_REAL)
+ } else {
+ rval = ip_getr (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_REAL)
+ }
+ if (and(swap, S_ALL) == S_ALL) # handle byte-swapping
+ call bswap4 (rval, 1, rval, 1, (SZ_REAL*SZB_CHAR))
+ O_TYPE(o) = TY_REAL
+
+ case GETR8:
+ if (nargs == 0) {
+ dval = ip_getd (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_DOUBLE)
+ } else {
+ dval = ip_getd (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_DOUBLE)
+ }
+ if (and(swap, S_ALL) == S_ALL) # handle byte-swapping
+ call bswap8 (dval, 1, dval, 1, (SZ_DOUBLE*SZB_CHAR))
+ O_TYPE(o) = TY_DOUBLE
+
+ case GETN, GETN4:
+ if (nargs == 0) {
+ rval = ip_getn (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_REAL)
+ } else {
+ rval = ip_getn (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_REAL)
+ }
+ if (and(swap, S_ALL) == S_ALL) # handle byte-swapping
+ call bswap4 (rval, 1, rval, 1, (SZ_REAL*SZB_CHAR))
+ O_TYPE(o) = TY_REAL
+
+ case GETN8:
+ if (nargs == 0) {
+ dval = ip_getn8 (fd, cur_offset)
+ cur_offset = cur_offset + (SZB_CHAR * SZ_DOUBLE)
+ } else {
+ dval = ip_getn8 (fd, O_VALI(args[1]))
+ cur_offset = O_VALI(args[1]) + (SZB_CHAR * SZ_DOUBLE)
+ }
+ if (and(swap, S_ALL) == S_ALL) # handle byte-swapping
+ call bswap8 (dval, 1, dval, 1, (SZ_DOUBLE*SZB_CHAR))
+ O_TYPE(o) = TY_DOUBLE
+
+ case LOCATE: # locate the pattern in the file
+ if (nargs == 1)
+ ival = ip_locate (fd, cur_offset, O_VALC(args[1]))
+ else if (nargs == 2)
+ ival = ip_locate (fd, O_VALI(args[1]), O_VALC(args[2]))
+ if (ival == ERR)
+ ival = 1
+ O_TYPE(o) = TY_INT
+ cur_offset = ival
+
+ case LINE: # locate the line no. in the file
+ ival = ip_line (fd, O_VALI(args[1]))
+ if (ival == ERR)
+ ival = 1
+ O_TYPE(o) = TY_INT
+ cur_offset = ival
+
+ case SKIP: # skip a certain number of bytes
+ ival = O_VALI(args[1])
+ O_TYPE(o) = TY_INT
+ cur_offset = cur_offset + ival
+
+ case BSWAP: # byte-swap argument
+ O_TYPE(o) = O_TYPE(args[1])
+ switch (O_TYPE(args[1])) {
+ case TY_SHORT:
+ call bswap2 (O_VALS(args[1]), 1, sval, 1, (SZ_SHORT*SZB_CHAR))
+ case TY_INT:
+ call bswap4 (O_VALI(args[1]), 1, ival, 1, (SZ_INT32*SZB_CHAR))
+ case TY_LONG:
+ call bswap4 (O_VALL(args[1]), 1, ival, 1, (SZ_LONG*SZB_CHAR))
+ case TY_REAL:
+ call bswap4 (O_VALR(args[1]), 1, rval, 1, (SZ_REAL*SZB_CHAR))
+ case TY_DOUBLE:
+ call bswap8 (O_VALD(args[1]), 1, dval, 1, (SZ_DOUBLE*SZB_CHAR))
+ }
+
+ case PARAMETER: # return current task parameter value
+ if (streq(O_VALC(args[1]),"dims")) {
+ call clgstr ("dims", Memc[outstr], SZ_FNAME)
+ len = strlen (Memc[outstr]) + 1
+ call ip_initop (o, len, TY_CHAR)
+ call strcpy (Memc[outstr], O_VALC(o), len)
+ } else if (streq(O_VALC(args[1]),"pixtype")) {
+ call clgstr ("pixtype", Memc[outstr], SZ_FNAME)
+ len = strlen (Memc[outstr]) + 1
+ call ip_initop (o, len, TY_CHAR)
+ call strcpy (Memc[outstr], O_VALC(o), len)
+ } else if (streq(O_VALC(args[1]),"interleave")) {
+ ival = clgeti ("interleave")
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"bswap")) {
+ call clgstr ("bswap", Memc[outstr], SZ_FNAME)
+ if (strne("no",Memc[outstr]) && strne("none",Memc[outstr]))
+ ival = YES
+ else
+ ival = NO
+ O_TYPE(o) = TY_BOOL
+ } else if (streq(O_VALC(args[1]),"hskip")) {
+ ival = clgeti ("hskip")
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"tskip")) {
+ ival = clgeti ("tskip")
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"bskip")) {
+ ival = clgeti ("bskip")
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"lskip")) {
+ ival = clgeti ("lskip")
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"lpad")) {
+ ival = clgeti ("lpad")
+ O_TYPE(o) = TY_INT
+ }
+
+ case DEFAULT: # return default task parameter value
+ if (streq(O_VALC(args[1]),"dims")) {
+ call ip_initop (o, 1, TY_CHAR)
+ call strcpy ("", O_VALC(o), 1)
+ } else if (streq(O_VALC(args[1]),"pixtype")) {
+ call ip_initop (o, 1, TY_CHAR)
+ call strcpy ("", O_VALC(o), 1)
+ } else if (streq(O_VALC(args[1]),"interleave")) {
+ ival = DEF_INTERLEAVE
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"bswap")) {
+ ival = DEF_SWAP
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"hskip")) {
+ ival = DEF_HSKIP
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"tskip")) {
+ ival = DEF_TSKIP
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"bskip")) {
+ ival = DEF_BSKIP
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"lskip")) {
+ ival = DEF_LSKIP
+ O_TYPE(o) = TY_INT
+ } else if (streq(O_VALC(args[1]),"lpad")) {
+ ival = DEF_LPAD
+ O_TYPE(o) = TY_INT
+ }
+
+ case LSB_HOST: # host is an LSB byte ordered machine
+ if (BYTE_SWAP2 == YES)
+ ival = YES
+ else
+ ival = NO
+ O_TYPE(o) = TY_BOOL
+
+ case MSB_HOST: # host is an MSB byte ordered machine
+ if (BYTE_SWAP2 == NO)
+ ival = YES
+ else
+ ival = NO
+ O_TYPE(o) = TY_BOOL
+
+ case SUBSTR: # return a substring of the argument
+
+ case STRIDX: # return offset of a char w/in str
+
+ }
+
+ # Write result to output operand.
+ O_LEN(o) = 0
+ switch (O_TYPE(o)) {
+ case TY_USHORT, TY_SHORT:
+ O_VALS(o) = sval
+ case TY_INT, TY_BOOL:
+ O_VALI(o) = ival
+ case TY_LONG:
+ O_VALL(o) = ival
+ case TY_REAL:
+ O_VALR(o) = rval
+ case TY_DOUBLE:
+ O_VALD(o) = dval
+ }
+
+ if (DEBUG) { call eprintf("ip_dbfcn: ") ; call zzi_pevop (o) }
+
+ IP_OFFSET(ip) = cur_offset
+ call sfree (sp)
+end
+
+
+# IP_DBSTR -- Get a string valued expression from the database.
+
+procedure ip_dbstr (ip, param, outstr, maxch)
+
+pointer ip #i task struct pointer
+char param[ARB] #i parameter to evaluate
+char outstr[ARB] #o result string
+int maxch #i max length of string
+
+pointer sp, expr, o
+
+int locpr(), strlen()
+pointer evvexpr()
+extern ip_getop(), ip_dbfcn()
+errchk evvexpr
+
+begin
+ call smark (sp)
+ call salloc (expr, SZ_EXPR, TY_CHAR)
+ call aclrc (Memc[expr], SZ_EXPR)
+
+ # Get the requested parameter.
+ call aclrc (outstr, SZ_EXPR)
+ call fdbgstr (IP_FSYM(ip), param, Memc[expr], SZ_EXPR)
+ if (Memc[expr] == EOS)
+ call error (1, "FDBGET: Format parameter not found")
+
+ if (DEBUG) {
+ call eprintf("ip_dbstr: expr='%s' len=%d ");call pargstr(Memc[expr])
+ call pargi(strlen(Memc[expr]))
+ }
+
+ # Evaluate the expression.
+ iferr {
+ o = evvexpr (Memc[expr], locpr(ip_getop), ip,
+ locpr(ip_dbfcn), ip, EV_RNGCHK)
+ if (O_TYPE(o) != TY_CHAR)
+ call error (0, "ip_dbstr: Expression must be a string valued")
+ else
+ call amovc (O_VALC(o), outstr, (min(strlen(O_VALC(o)),maxch)))
+ } then
+ call erract (EA_WARN)
+
+ if (DEBUG) { call eprintf ("outstr=:%s:\n") ; call pargstr (outstr) }
+
+ call evvfree (o)
+ call sfree (sp)
+end
+
+$for (ir)
+
+$if (datatype == i)
+# IP_DBGETI -- Get integer valued format parameter from the database.
+$else
+# IP_DBGETR -- Get real valued format parameter from the database.
+$endif
+
+PIXEL procedure ip_dbget$t (ip, param)
+
+pointer ip #i task struct pointer
+char param[ARB] #i requested parameter
+
+PIXEL val
+pointer sp, expr, o
+
+int locpr()
+pointer evvexpr()
+extern ip_getop(), ip_dbfcn()
+errchk evvexpr
+
+begin
+ call smark (sp)
+ call salloc (expr, SZ_EXPR, TY_CHAR)
+
+ # Get the requested parameter.
+ call fdbgstr (IP_FSYM(ip), param, Memc[expr], SZ_EXPR)
+ if (Memc[expr] == EOS)
+ call error (1, "IP_DBGET: Format parameter not found")
+
+ # Evaluate the expression.
+ if (DEBUG) {
+ call eprintf ("ip_dbget: expr='%s'\n")
+ call pargstr (Memc[expr])
+ call flush (STDERR)
+ }
+ iferr {
+ o = evvexpr (Memc[expr], locpr(ip_getop), ip,
+ locpr(ip_dbfcn), ip, EV_RNGCHK)
+ if (O_TYPE(o) == TY_BOOL) {
+ val = O_VALI(o)
+ $if (datatype == i)
+ } else if (O_TYPE(o) != TY_PIXEL && O_TYPE(o) != TY_SHORT) {
+ call error (0, "Expression must be an integer")
+ $else
+ } else if (O_TYPE(o) != TY_PIXEL) {
+ call error (0, "Expression must be a real")
+ $endif
+ } else
+ val = O_VAL$T(o)
+
+ if (DEBUG) {
+ call eprintf ("ip_dbget: val=%d type=%d ecpr=:%s:\n")
+ call parg$t (val)
+ call pargi (O_TYPE(o))
+ call pargstr (Memc[expr])
+ call flush (STDERR)
+ }
+ } then
+ call erract (EA_WARN)
+
+ call evvfree (o)
+ call sfree (sp)
+ return (val)
+end
+$endfor
+
+# IP_DO_ERROR -- Process the error parameter.
+
+procedure ip_do_error (ip, expr)
+
+pointer ip #i task struct pointer
+char expr[ARB] #i error string
+
+pointer o
+
+int locpr()
+pointer evvexpr()
+extern ip_getop(), ip_dbfcn()
+bool strne()
+errchk evvexpr
+
+begin
+ if (DEBUG) {call eprintf ("error expr: '%s' ") ; call pargstr (expr)}
+
+ # Evaluate the expression.
+ iferr {
+ o = evvexpr (expr, locpr(ip_getop), ip, locpr(ip_dbfcn), ip,
+ EV_RNGCHK)
+
+ if (DEBUG) { call eprintf("-> '%s'\n") ; call pargstr(O_VALC(o)) }
+
+ if (O_TYPE(o) != TY_CHAR)
+ call error (2, "do_error: Expression must be a string valued")
+ else {
+ if (strne("okay",O_VALC(o)))
+ call error (2, O_VALC(o))
+ }
+ call evvfree (o)
+
+ } then
+ if (IP_OUTPUT(ip) != IP_INFO)
+ call erract (EA_FATAL)
+end
+
+
+# IP_DO_COMMENT - Process a comment line in the format database.
+
+procedure ip_do_comment (ip, comstr)
+
+pointer ip #i task struct pointer
+char comstr[ARB] #i comment to add
+
+pointer sp, buf
+
+begin
+ # Copy the comment line to the comment block.
+ if (IP_COMPTR(ip) == NULL)
+ call calloc (IP_COMPTR(ip), SZ_COMMENT, TY_CHAR)
+
+ if (COMMENT(ip) == '\0') {
+ call strcpy ("\t", COMMENT(ip), SZ_LINE)
+ call strcat (comstr, COMMENT(ip), SZ_LINE)
+ } else {
+ call smark (sp)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+
+ Memc[buf] = '\0'
+ call strcpy ("\t", Memc[buf], SZ_LINE)
+ call strcat (comstr, Memc[buf], SZ_LINE)
+ call strcat ("\n", Memc[buf], SZ_LINE)
+ call strcat (COMMENT(ip), Memc[buf], SZ_COMMENT)
+
+ call strcpy (Memc[buf], COMMENT(ip), SZ_COMMENT)
+
+ call sfree (sp)
+ }
+end
+
+
+# IP_INITOP - Initialize an operand pointer to the requested values
+
+procedure ip_initop (o, len, type)
+
+pointer o #u operand pointer
+int len #i length of array
+int type #i data type of operand
+
+begin
+ O_LEN(o) = len
+ O_TYPE(o) = type
+ if (len > 1)
+ call calloc (O_VALP(o), len, type)
+end
diff --git a/pkg/dataio/import/ipfcn.h b/pkg/dataio/import/ipfcn.h
new file mode 100644
index 00000000..090c040e
--- /dev/null
+++ b/pkg/dataio/import/ipfcn.h
@@ -0,0 +1,57 @@
+# IPFCN.H - Include file for the special functions supported by the IMPORT task.
+
+# Format database functions.
+define DB_FUNCTIONS "|ctocc|ctod|ctoi|ctol|ctor|ctowrd|\
+ |getstr|getb|getu|geti|geti2|geti4|\
+ |getr|getr4|getr8|getn|getn4|getn8|\
+ |locate|line|skip|bswap|parameter|default|\
+ |lsb_host|msb_host|substr|stridx|"
+
+define CTOCC 1 # Convert character to printable char constant
+define CTOD 2 # Convert string to double precision real
+define CTOI 3 # Convert string to integer
+define CTOL 4 # Convert string to long
+define CTOR 5 # Convert string to single precision real
+define CTOWRD 6 # Return 1st white-space delimited word from str
+# newline
+define GETSTR 8 # Get a string at offset
+define GETB 9 # Get a byte at offset
+define GETU 10 # Get an unsigned short int at offset
+define GETI 11 # Get a signed int at offset
+define GETI2 12 # Get a signed int at offset
+define GETI4 13 # Get a long signed int at offset
+# newline
+define GETR 15 # Get an IEEE fp number at offset
+define GETR4 16 # Get an IEEE fp number at offset
+define GETR8 17 # Get an IEEE double precision number at offset
+define GETN 18 # Get a native fp number at offset
+define GETN4 19 # Get a native fp number at offset
+define GETN8 20 # Get a native double precision number at offset
+# newline
+define LOCATE 22 # Compute an offset
+define LINE 23 # Offset of line N
+define SKIP 24 # Move offset N-bytes
+define BSWAP 25 # Byte swap the argument
+define PARAMETER 26 # Return current task parameter
+define DEFAULT 27 # Return default task parameter
+# newline
+define LSB_HOST 29 # Host is LSB byte ordered machine
+define MSB_HOST 30 # Host is MSB byte ordered machine
+define SUBSTR 31 # Return a substring of the argument
+define STRIDX 32 # Return occurance of a char within a string
+
+
+# Outbands expression functions.
+define OB_FUNCTIONS "|gray|grey|flipx|flipy|\
+ |red|green|blue|"
+
+define GRAY 1 # Convert to NTSC grayscale
+define GREY 2 # Convert to NTSC grayscale (alias)
+define FLIPX 3 # Flip image in X
+define FLIPY 4 # Flip image in Y
+# newline
+define RED 6 # Get red component of colormap image
+define GREEN 7 # Get green component of colormap image
+define BLUE 8 # Get blue component of colormap image
+
+
diff --git a/pkg/dataio/import/ipfio.gx b/pkg/dataio/import/ipfio.gx
new file mode 100644
index 00000000..61147ea2
--- /dev/null
+++ b/pkg/dataio/import/ipfio.gx
@@ -0,0 +1,443 @@
+include <mach.h>
+include <fset.h>
+include "../import.h"
+
+define DEBUG false
+
+
+# IP_GSTR -- Get a string of the specifed length from the given offset.
+
+procedure ip_gstr (fd, offset, len, outstr)
+
+int fd
+int offset
+int len
+char outstr[ARB]
+
+int nstat, read()
+pointer sp, buf
+
+begin
+ call smark (sp)
+ call salloc (buf, len+2, TY_CHAR)
+ call aclrc (Memc[buf], len+2)
+ call aclrc (outstr, len+2)
+
+ call ip_lseek (fd, offset)
+ nstat = read (fd, Memc[buf], len)
+
+ if (mod(offset,2) == 0 && offset > 1)
+ call bytmov (Memc[buf], 2, Memc[buf], 1, len)
+ call chrupk (Memc[buf], 1, outstr, 1, len)
+
+ if (DEBUG) { call eprintf ("ip_gstr: :%s: len=%d\n");
+ call pargstr(outstr) ; call pargi (len) }
+ call sfree (sp)
+end
+
+
+# IP_GETB -- Get a byte from the given offset.
+
+short procedure ip_getb (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+short val
+char buf[2]
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, buf, 2)
+
+ if (mod(offset,2) == 0)
+ call bytmov (buf, 2, buf, 1, 2)
+ call chrupk (buf, 1, buf, 1, 2)
+
+ if (DEBUG) { call eprintf ("ip_getb: %d\n"); call pargs(buf[1]) }
+ if (buf[1] < 0)
+ val = buf[1] + 256
+ else
+ val = buf[1]
+ return (val)
+end
+
+
+# IP_GETU -- Get a unsigned short integer from the given offset.
+
+int procedure ip_getu (fd, offset)
+
+int fd
+int offset
+
+int val
+short ip_gets()
+
+begin
+ val = ip_gets (fd, offset)
+ if (val < 0)
+ val = val + 65536
+ return (val)
+end
+
+# IP_GET[silrd] -- Get a value of <type> from the given offset.
+
+$for (silrd)
+
+PIXEL procedure ip_get$t (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+PIXEL val
+
+begin
+ call ip_lseek (fd, offset)
+ $if (datatype == il)
+ nstat = read (fd, val, SZ_INT32 * SZB_CHAR)
+ if (SZ_INT != SZ_INT32)
+ call iupk32 (val, val, 1)
+ $else
+ nstat = read (fd, val, SZ_PIXEL * SZB_CHAR)
+ $endif
+ $if (datatype == rd)
+ call ieeupk$t (val)
+ $endif
+
+ if (DEBUG) { call eprintf ("ip_get: %g\n"); call parg$t(val) }
+ return (val)
+end
+$endfor
+
+# IP_GETN -- Get a native floating point number from the given offset.
+
+real procedure ip_getn (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+real rval
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, rval, SZ_REAL)
+
+ if (DEBUG) { call eprintf ("ip_getn: %g\n"); call pargr(rval) }
+ return (rval)
+end
+
+
+# IP_GETN8 -- Get a native double precision floating point number from the
+# given offset.
+
+double procedure ip_getn8 (fd, offset)
+
+int fd
+int offset
+
+int nstat, read()
+double dval
+
+begin
+ call ip_lseek (fd, offset)
+ nstat = read (fd, dval, SZ_DOUBLE)
+
+ if (DEBUG) { call eprintf ("ip_getn8: %g\n"); call pargd(dval) }
+ return (dval)
+end
+
+
+# IP_AGETB -- Get an array of bytes from the file. The data pointer is
+# allocated if necessary and contains the data on output.
+
+procedure ip_agetb (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+pointer sp, buf
+int fp, nval, nstat
+int ip_lnote(), read()
+
+begin
+ fp = ip_lnote(fd)
+ if (mod(fp,2) == 0 && fp != 1)
+ nval = len
+ else
+ nval = len + 1
+
+ call smark (sp)
+ call salloc (buf, nval, TY_CHAR)
+
+ if (ptr == NULL)
+ call malloc (ptr, nval * SZB_CHAR, TY_CHAR)
+ nstat = read (fd, Memc[buf], nval / SZB_CHAR + 1)
+
+ fp = ip_lnote(fd)
+ if (mod(fp,2) == 0 && fp != 1)
+ call bytmov (Memc[buf], 2, Memc[buf], 1, nval)
+ call achtbc (Memc[buf], Memc[ptr], len)
+
+ call sfree (sp)
+end
+
+
+# IP_AGETU -- Get an array of <type> from the file. The data pointer is
+# allocated if necessary and contains the data on output.
+
+procedure ip_agetu (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+begin
+ call ip_agets (fd, ptr, len)
+ call achtsu (Mems[ptr], Mems[ptr], len)
+end
+
+
+# IP_AGET[silrd] -- Get an array of <type> from the file. The data pointer is
+# allocated if necessary and contains the data on output.
+
+$for (silrd)
+procedure ip_aget$t (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+int nstat
+int read()
+
+begin
+ if (ptr == NULL)
+ call malloc (ptr, len, TY_PIXEL)
+ $if (datatype == il)
+ nstat = read (fd, Mem$t[ptr], len * SZ_INT32)
+ if (SZ_INT != SZ_INT32)
+ call iupk32 (Mem$t[ptr], Mem$t[ptr], len)
+ $else
+ nstat = read (fd, Mem$t[ptr], len * SZ_PIXEL)
+ $endif
+ $if (datatype == rd)
+ call ieevupk$t (Mem$t[ptr], Mem$t[ptr], len)
+ $endif
+end
+
+$endfor
+
+# IP_AGETN -- Get an array of native floats from the file. The data pointer is
+# allocated if necessary and contains the data on output.
+
+procedure ip_agetn (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+int nstat
+int read()
+
+begin
+ if (ptr == NULL)
+ call malloc (ptr, len, TY_REAL)
+ nstat = read (fd, Memr[ptr], len * SZ_REAL)
+end
+
+
+# IP_AGETN8 -- Get an array of native doubles from the file. The data pointer
+# is allocated if necessary and contains the data on output.
+
+procedure ip_agetn8 (fd, ptr, len)
+
+int fd #i file descriptor
+pointer ptr #i data pointer
+int len #i length of array
+
+int nstat
+int read()
+
+begin
+ if (ptr == NULL)
+ call malloc (ptr, len, TY_DOUBLE)
+ nstat = read (fd, Memd[ptr], len * SZ_DOUBLE)
+end
+
+
+# -----------------------------------------------------------------
+# ------------------ UTILITY FILE I/O FUNCTIONS -------------------
+# -----------------------------------------------------------------
+
+
+define BLKSIZE 1024
+
+# IP_LINE -- Return the offset of the start of the given line number.
+
+int procedure ip_line (fd, line)
+
+int fd #i input file descriptor
+int line #i line number to search
+
+pointer sp, cbuf, buf
+int nl, offset, i, nread, fsize
+
+int read(), fstati()
+
+define done_ 99
+define err_ 98
+
+begin
+ if (line == 1) {
+ return (1)
+ } else {
+ call smark (sp)
+ call salloc (buf, BLKSIZE, TY_CHAR)
+ call salloc (cbuf, BLKSIZE, TY_CHAR)
+
+ # Rewind file descriptor
+ call ip_lseek (fd, BOF)
+ nl = 1
+ offset = 1
+
+ nread = BLKSIZE / SZB_CHAR
+ fsize = fstati (fd, F_FILESIZE)
+ while (read (fd, Memc[buf], nread) != EOF) {
+ # Convert it to spp chars.
+ call ip_lskip (fd, nread)
+ call chrupk (Memc[buf], 1, Memc[cbuf], 1, BLKSIZE)
+ do i = 1, BLKSIZE {
+ if (Memc[cbuf+i-1] == '\n') {
+ nl = nl + 1
+ offset = offset + 1
+ if (nl == line)
+ goto done_
+ } else
+ offset = offset + 1
+ if (offset >= fsize)
+ goto err_
+ }
+ }
+err_ call sfree (sp)
+ call ip_lseek (fd, BOF)
+ return (ERR)
+
+done_ if (DEBUG) { call eprintf("ip_line: '%s'\n"); call pargi(offset) }
+ call sfree (sp)
+ call ip_lseek (fd, offset)
+ return (offset)
+ }
+end
+
+
+# IP_LOCATE -- Return the offset of the start of the given pattern.
+
+int procedure ip_locate (fd, offset, pattern)
+
+int fd #i input file descriptor
+int offset #i offset to begin search
+char pattern[ARB] #i pattern to locate
+
+pointer sp, cbuf, buf
+int fsize, nread, patlen, cur_offset, loc
+
+int fstati(), read(), strsearch(), strlen()
+
+define done_ 99
+
+begin
+ # Rewind file descriptor
+ call ip_lseek (fd, offset)
+ cur_offset = offset
+
+ call smark (sp)
+ call salloc (buf, BLKSIZE, TY_CHAR)
+ call salloc (cbuf, BLKSIZE, TY_CHAR)
+
+ if (DEBUG) { call eprintf("ip_loc: offset %d\n"); call pargi(offset)}
+
+ nread = BLKSIZE / SZB_CHAR
+ fsize = fstati (fd, F_FILESIZE)
+ patlen = strlen (pattern)
+ while (read (fd, Memc[buf], nread) != EOF) {
+ # Convert it to spp chars.
+ call ip_lskip (fd, nread)
+ call chrupk (Memc[buf], 1, Memc[cbuf], 1, BLKSIZE)
+ loc = strsearch (Memc[cbuf], pattern)
+ if (loc != 0) {
+ cur_offset = cur_offset + loc - 1 - patlen
+ goto done_
+ } else {
+ # Allow some overlap in case the pattern broke over the blocks.
+ cur_offset = cur_offset + BLKSIZE - 2 * patlen
+ call ip_lseek (fd, cur_offset)
+ if (cur_offset + BLKSIZE > fsize)
+ nread = fsize - cur_offset + 1
+ }
+ }
+ call sfree (sp)
+ call ip_lseek (fd, BOF)
+ return (ERR)
+
+done_ if (DEBUG) { call eprintf("ip_loc: %d\n"); call pargi(cur_offset)}
+ call sfree (sp)
+ call ip_lseek (fd, offset)
+ return (cur_offset)
+end
+
+
+# IP_LSEEK -- Set the file position as a byte offset.
+
+procedure ip_lseek (fd, offset)
+
+int fd #i file descriptor
+int offset #i requested offset
+
+long cur_offset, where, fsize
+int fstati()
+common /fiocom/ cur_offset
+
+begin
+ if (offset == BOF || offset == ERR) {
+ cur_offset = 1
+ call seek (fd, BOF)
+ } else {
+ fsize = fstati (fd, F_FILESIZE) * SZB_CHAR
+ cur_offset = min (fsize, offset)
+ where = min (fsize, (offset/SZB_CHAR+mod(offset,2)))
+ call seek (fd, where)
+ }
+end
+
+
+# IP_LNOTE -- Note the file position as a byte offset.
+
+int procedure ip_lnote (fd)
+
+int fd #i file descriptor (unused)
+
+long cur_offset
+common /fiocom/ cur_offset
+
+begin
+ return (cur_offset)
+end
+
+
+# IP_LSKIP -- Bump the file position by a byte offset.
+
+procedure ip_lskip (fd, skip)
+
+int fd #i file descriptor
+int skip
+
+long cur_offset
+common /fiocom/ cur_offset
+
+begin
+ call ip_lseek (fd, cur_offset+skip)
+end
diff --git a/pkg/dataio/import/ipinfo.x b/pkg/dataio/import/ipinfo.x
new file mode 100644
index 00000000..3ded4a2d
--- /dev/null
+++ b/pkg/dataio/import/ipinfo.x
@@ -0,0 +1,256 @@
+include "import.h"
+
+
+# IP_INFO -- Print information about the binary file.
+
+procedure ip_info (ip, fname, verbose)
+
+pointer ip #i task struct pointer
+char fname[ARB] #i binary file name
+int verbose #i verbose output?
+
+pointer sp, buf
+pointer fmt
+int fdb
+int locpr(), fdb_opendb()
+
+pointer fdb_scan_records()
+extern ip_getop(), ip_dbfcn()
+
+begin
+ if (IP_BLTIN(ip) == YES) {
+ call ip_bltin_info (ip, fname, verbose)
+
+ } else if (IP_FORMAT(ip) == IP_NONE) {
+ call ip_prinfo (ip, "User Specified Format", fname, verbose)
+
+ } else {
+ call smark (sp)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+
+ if (IP_FSYM(ip) == NULL) {
+ fdb = fdb_opendb ()
+ fmt = fdb_scan_records (fdb, "image_id",
+ locpr(ip_getop), ip, locpr(ip_dbfcn), ip)
+ call fdbgstr (fmt, "id_string", Memc[buf], SZ_LINE)
+ call fdb_strip_quote (Memc[buf], Memc[buf], SZ_EXPR)
+ call ip_prinfo (ip, Memc[buf], fname, verbose)
+ call fdb_close (fmt)
+ call fdb_closedb (fdb)
+ } else {
+ call fdbgstr (IP_FSYM(ip), "id_string", Memc[buf], SZ_LINE)
+ call fdb_strip_quote (Memc[buf], Memc[buf], SZ_EXPR)
+ call ip_prinfo (ip, Memc[buf], fname, verbose)
+ }
+
+ call sfree (sp)
+ }
+end
+
+
+# IP_PRINFO -- Print information about the binary file.
+
+procedure ip_prinfo (ip, format, fname, verbose)
+
+pointer ip #i task struct pointer
+char format #i format name
+char fname[ARB] #i binary file name
+int verbose #i verbose output?
+
+int i
+bool itob()
+
+define done_ 99
+
+begin
+ #call printf ("Input file:\n\t")
+ if (verbose == NO) {
+ call printf ("%s: %20t")
+ call pargstr (fname)
+ do i = 1, IP_NDIM(ip) {
+ call printf ("%d ")
+ call pargi (IP_AXLEN(ip,i))
+ if (i < IP_NDIM(ip))
+ call printf ("x ")
+ }
+ call printf (" \t%s\n")
+ call pargstr (format)
+
+ # Print out the format comment if any.
+# if (IP_COMPTR(ip) != NULL) {
+# if (COMMENT(ip) != '\0') {
+# call printf ("%s\n")
+# call pargstr (COMMENT(ip))
+# }
+# call strcpy ("\0", COMMENT(ip), SZ_LINE)
+# }
+ return
+ }
+
+ # Print a more verbose description.
+ call printf ("%s: %20t%s\n")
+ call pargstr (fname)
+ call pargstr (format)
+
+ # Print out the format comment if any.
+ if (IP_COMPTR(ip) != NULL) {
+ if (COMMENT(ip) != '\0') {
+ call printf ("%s\n")
+ call pargstr (COMMENT(ip))
+ }
+ call strcpy ("\0", COMMENT(ip), SZ_LINE)
+ }
+
+ # Print the image size.
+ if (IP_NDIM(ip) > 0) {
+ call printf ("%20tResolution:%38t")
+ do i = 1, IP_NDIM(ip) {
+ call printf ("%d ")
+ call pargi (IP_AXLEN(ip,i))
+ if (i < IP_NDIM(ip))
+ call printf ("x ")
+ }
+ call printf ("\n")
+ }
+
+ # Print other information.
+ if (PTYPE(ip,1) != NULL) {
+ call printf ("%20tPixel type: %38t%d-bit ")
+ call pargi (8 * IO_NBYTES(PTYPE(ip,1)))
+ switch (IO_TYPE(PTYPE(ip,1))) {
+ case PT_UINT:
+ call printf ("unsigned integer\n")
+ case PT_INT:
+ call printf ("signed integer\n")
+ case PT_IEEE:
+ call printf ("IEEE floating point\n")
+ case PT_NATIVE:
+ call printf ("native floating point\n")
+ default:
+ call printf ("\n")
+ }
+ }
+
+ call printf ("%20tPixel storage: %38t%s\n")
+ if (BAND_INTERLEAVED(ip))
+ call pargstr ("non-interleaved")
+ else if (LINE_INTERLEAVED(ip))
+ call pargstr ("line-interleaved")
+ else if (PIXEL_INTERLEAVED(ip))
+ call pargstr ("pixel-interleaved")
+ else
+ call pargstr ("unknown")
+ call printf ("%20tHeader length: %38t%d bytes\n")
+ call pargi (IP_HSKIP(ip))
+ call printf ("%20tByte swapped: %38t%b\n")
+ call pargb (itob(IP_SWAP(ip)))
+end
+
+
+# IP_OBINFO - Print information about the output image contents.
+
+procedure ip_obinfo (ip, imname)
+
+pointer ip #i ip struct pointer
+char imname[ARB] #i image name
+
+int i, nb
+
+begin
+ call printf (" Output image:\n")
+
+ if (IP_NBANDS(ip) != ERR) {
+ nb = IP_NBANDS(ip)
+ do i = 1, nb {
+ call printf ("\t%s[*,*,%d]:%30t==> %s %s\n")
+ call pargstr (imname)
+ call pargi (i)
+ call pargstr (O_EXPR(ip,i))
+ if (i == 1)
+ call pargstr (" # outbands expr")
+ else
+ call pargstr (" ")
+ }
+ } else {
+ nb = max (IP_AXLEN(ip,3), max (IP_INTERLEAVE(ip), IP_NPIXT(ip)))
+ do i = 1, nb {
+ call printf ("\t%s[*,*,%d]:%30t==> %s%d %s\n")
+ call pargstr (imname)
+ call pargi (i)
+ call pargstr ("b")
+ call pargi (i)
+ if (i == 1)
+ call pargstr (" # outbands expr")
+ else
+ call pargstr (" ")
+ }
+ }
+
+end
+
+
+# IP_LIST_FORMATS -- List the formats in the database. The DB is scanned
+# and the format name for each record found, as well as the verbose ID
+# string is printed on the standard output. The file position is left at
+# the same place on exit.
+
+procedure ip_list_formats (fd)
+
+int fd #i input binary file descriptor
+
+pointer sp, format, idstr, alias
+pointer fmt, ap[5]
+int i, nsym, cur_offset
+
+int note()
+pointer stfindall(), fdb_next_rec()
+
+begin
+ # Save current file offset.
+ cur_offset = note (fd)
+
+ call smark (sp)
+ call salloc (format, SZ_EXPR, TY_CHAR)
+ call salloc (idstr, SZ_EXPR, TY_CHAR)
+ call salloc (alias, SZ_LINE, TY_CHAR)
+
+ # Loop through the database records.
+ call seek (fd, BOF)
+ fmt = NULL
+ call printf ("Format%15tAliases%36tFormat Identification\n")
+ call printf ("------%15t-------%36t---------------------\n")
+ repeat {
+ fmt = fdb_next_rec (fd)
+ if (fmt == NULL)
+ break
+ call fdbgstr (fmt, "format", Memc[format], SZ_EXPR)
+ call fdbgstr (fmt, "id_string", Memc[idstr], SZ_EXPR)
+ call fdb_strip_quote (Memc[idstr], Memc[idstr], SZ_EXPR)
+
+ # Generate a list of aliases for the format.
+ call aclrc (Memc[alias], SZ_LINE)
+ nsym = stfindall (fmt, "alias", ap, 5)
+ if (nsym >= 1) {
+ do i = nsym, 1, -1 {
+ call strcat (Memc[P2C(ap[i])], Memc[alias], SZ_LINE)
+ if (i > 1)
+ call strcat (",", Memc[alias], SZ_LINE)
+ }
+ } else
+ Memc[alias] = EOS
+
+ # Print the information
+ call printf ("%s%15t%.20s%36t%s\n")
+ call pargstr (Memc[format])
+ call pargstr (Memc[alias])
+ call pargstr (Memc[idstr])
+
+ call fdb_close (fmt)
+ call flush (STDOUT)
+ }
+
+ # Restore file offset.
+ call seek (fd, cur_offset)
+
+ call sfree (sp)
+end
diff --git a/pkg/dataio/import/iplistpix.x b/pkg/dataio/import/iplistpix.x
new file mode 100644
index 00000000..3f4a001d
--- /dev/null
+++ b/pkg/dataio/import/iplistpix.x
@@ -0,0 +1,137 @@
+include <imhdr.h>
+include <error.h>
+include <mwset.h>
+
+# IP_LISTPIXELS -- Convert image pixels into a text stream, i.e., into a list.
+# Each pixel is printed on a separate line, preceded by its coordinates.
+
+procedure ip_listpix (im)
+
+char wcs[SZ_FNAME]
+double incoords[IM_MAXDIM], outcoords[IM_MAXDIM]
+int i, j, npix, ndim, wcsndim, laxis1, fmtstat
+int paxno[IM_MAXDIM], laxno[IM_MAXDIM]
+long v[IM_MAXDIM], vcoords[IM_MAXDIM]
+pointer im, line, mw, ct, fmtptrs[IM_MAXDIM]
+
+int imgnlr(), mw_stati()
+pointer mw_openim(), mw_sctran()
+
+begin
+ # Get info from the input image.
+ ndim = IM_NDIM(im)
+ npix = IM_LEN(im,1)
+
+ # Get the wcs.
+ call strcpy ("world", wcs, SZ_FNAME)
+ ifnoerr (mw = mw_openim (im)) {
+ # Set up the transformation.
+ call mw_seti (mw, MW_USEAXMAP, NO)
+ ct = mw_sctran (mw, "logical", wcs, 0)
+ wcsndim = mw_stati (mw, MW_NPHYSDIM)
+
+ # Get the physical to logical axis map.
+ call mw_gaxmap (mw, paxno, laxno, wcsndim)
+
+ # Set the default wcs.
+ call mw_ssytem (mw, wcs)
+
+ } else {
+ # Print the error message from the above loop.
+ call erract (EA_WARN)
+
+ # Set the transform to the identity transform.
+ mw = NULL
+ ct = NULL
+ wcsndim = ndim
+
+ # Set the default physical to logical axis map.
+ do i = 1, wcsndim
+ paxno[i] = i
+ }
+
+ # Initialize the v vectors.
+ call amovkl (long (1), v, IM_MAXDIM)
+ call amovkl (long (1), vcoords, IM_MAXDIM)
+
+ # Initialize the coordinates.
+ laxis1 = 0
+ do i = 1, wcsndim {
+ if (paxno[i] == 0) {
+ incoords[i] = 1
+ } else if (paxno[i] == 1) {
+ laxis1 = i
+ incoords[i] = v[1]
+ } else {
+ incoords[i] = v[paxno[i]]
+ }
+ }
+
+ # Check and correct for the no axis mapping case.
+ if (laxis1 == 0) {
+ laxis1 = 1
+ do i = 1, wcsndim
+ paxno[i] = i
+ }
+
+ # Get the logical to physical axis map for the format strings.
+ do i = 1, ndim {
+ laxno[i] = 0
+ do j = 1, wcsndim {
+ if (paxno[j] != i)
+ next
+ laxno[i] = j
+ break
+ }
+ }
+
+ # Set the format strings for the logical axes.
+ fmtstat = EOS
+ do i = 1, ndim {
+ call malloc (fmtptrs[i], SZ_FNAME, TY_CHAR)
+ if (fmtstat != EOF)
+ call gargwrd (Memc[fmtptrs[i]], SZ_FNAME)
+ else
+ Memc[fmtptrs[i]] = EOS
+ if (laxno[i] == 0)
+ call strcpy ("%0.15g ", Memc[fmtptrs[i]], SZ_FNAME)
+ else if (mw == NULL || ct == NULL)
+ call strcpy ("%0.15g ", Memc[fmtptrs[i]], SZ_FNAME)
+ else iferr (call mw_gwattrs (mw, laxno[i], "format",
+ Memc[fmtptrs[i]], SZ_FNAME))
+ call strcpy ("%0.15g ", Memc[fmtptrs[i]], SZ_FNAME)
+ else
+ call strcat (" ", Memc[fmtptrs[i]], SZ_FNAME)
+ }
+
+ # Print the pixels.
+ while (imgnlr (im, line, v) != EOF) {
+ do i = 1, npix {
+ incoords[laxis1] = i
+ if (ct == NULL)
+ call amovd (incoords, outcoords, wcsndim)
+ else
+ call mw_ctrand (ct, incoords, outcoords, wcsndim)
+ do j = 1, ndim { # X, Y, Z, etc.
+ call printf (Memc[fmtptrs[j]])
+ if (laxno[j] == 0)
+ call pargd (double(vcoords[j]))
+ else
+ call pargd (outcoords[laxno[j]])
+ }
+ call printf (" %g\n") # pixel value
+ call pargr (Memr[line+i-1])
+ }
+ call amovl (v, vcoords, IM_MAXDIM)
+ do i = 1, wcsndim {
+ if (paxno[i] == 0)
+ next
+ incoords[i] = v[paxno[i]]
+ }
+ }
+
+ do i = 1, ndim
+ call mfree (fmtptrs[i], TY_CHAR)
+ if (mw != NULL)
+ call mw_close (mw)
+end
diff --git a/pkg/dataio/import/ipmkhdr.x b/pkg/dataio/import/ipmkhdr.x
new file mode 100644
index 00000000..c8432ed2
--- /dev/null
+++ b/pkg/dataio/import/ipmkhdr.x
@@ -0,0 +1,63 @@
+include <imhdr.h>
+include <ctype.h>
+include "import.h"
+
+define LEN_COMMENT 70 # Maximum comment length
+define COMMENT "COMMENT " # Comment key
+define IS_FITS (IS_DIGIT($1)||IS_UPPER($1)||($1=='-')||($1=='_'))
+
+# IP_MKHEADER -- Append or substitute new image header from an image or file.
+# Only the legal FITS cards (ignoring leading whitespace) will be copied
+# from a file.
+
+procedure ip_mkheader (im, fname)
+
+pointer im # IMIO pointer
+char fname[ARB] # Image or data file name
+
+int i, j
+pointer ua, fd
+pointer sp, str
+
+int open(), getline(), nowhite()
+pointer immap()
+errchk open
+
+begin
+ if (nowhite (fname, fname, SZ_FNAME) == 0)
+ return
+
+ ua = IM_USERAREA(im)
+ ifnoerr (fd = immap (fname, READ_ONLY, LEN_UA)) {
+ call strcpy (Memc[IM_USERAREA(fd)], Memc[ua], LEN_UA)
+ call imunmap (fd)
+ } else {
+ fd = open (fname, READ_ONLY, TEXT_FILE)
+
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ Memc[ua] = EOS
+ while (getline (fd, Memc[str]) != EOF) {
+ for (i=str; IS_WHITE(Memc[i]); i=i+1)
+ ;
+ for (j=i; IS_FITS(Memc[j]); j=j+1)
+ ;
+ for (; j<i+8 && Memc[j]==' '; j=j+1)
+ ;
+ if (j<i+8 && (Memc[j] != EOS || Memc[j] != '\n'))
+ next
+ if (Memc[j] == '=' && Memc[j+1] != ' ')
+ next
+ for (; j<i+80 && Memc[j] != EOS; j=j+1)
+ ;
+ if (Memc[j-1] != '\n') {
+ Memc[j] = '\n'
+ Memc[j+1] = EOS
+ }
+ call strcat (Memc[i], Memc[ua], LEN_UA)
+ }
+ call sfree (sp)
+ call close (fd)
+ }
+end
diff --git a/pkg/dataio/import/ipobands.gx b/pkg/dataio/import/ipobands.gx
new file mode 100644
index 00000000..be568818
--- /dev/null
+++ b/pkg/dataio/import/ipobands.gx
@@ -0,0 +1,306 @@
+include <error.h>
+include <mach.h>
+include <evvexpr.h>
+include <fset.h>
+include "../import.h"
+include "../ipfcn.h"
+
+define DEBUG false
+define VDEBUG false
+
+
+# IP_GETOP -- Called by evvexpr to get an operand.
+
+procedure ip_getop (ip, opname, o)
+
+pointer ip #i task struct pointer
+char opname[ARB] #i operand name to retrieve
+pointer o #o output operand pointer
+
+int i, nops, found, optype
+pointer sp, buf
+pointer op
+
+int fstati(), ip_ptype(), strlen(), strncmp()
+bool streq()
+
+begin
+ # First see if it's one of the special file operands.
+ if (opname[1] == '$') {
+ if (strncmp(opname, "$FSIZE", 3) == 0) {
+ O_LEN(o) = 0
+ O_TYPE(o) = TY_INT
+ O_VALI(o) = fstati (IP_FD(ip), F_FILESIZE) * SZB_CHAR
+ } else if (strncmp(opname, "$FNAME", 3) == 0) {
+ call smark (sp)
+ call salloc (buf, SZ_FNAME, TY_CHAR)
+
+ call fstats (IP_FD(ip), F_FILENAME, Memc[buf], SZ_FNAME)
+
+ O_TYPE(o) = TY_CHAR
+ O_LEN(o) = strlen (Memc[buf]) + 1
+ call malloc (O_VALP(o), O_LEN(o), TY_CHAR)
+ call strcpy (Memc[buf], O_VALC(o), i)
+ call sfree (sp)
+ }
+
+ return
+ }
+
+ nops = IP_NPIXT(ip)
+ found = NO
+ do i = 1, nops {
+ # Search for operand name which matches requested value.
+ op = PTYPE(ip,i)
+ if (streq (Memc[IO_TAG(op)],opname)) {
+ found = YES
+ break
+ }
+ }
+
+ if (VDEBUG) {
+ call eprintf ("getop: opname=%s tag=%s found=%d ")
+ call pargstr(opname) ; call pargstr(Memc[IO_TAG(op)])
+ call pargi(found)
+ if (found == YES) call zzi_prop (op)
+ }
+
+ if (found == YES) {
+ # Copy operand descriptor to 'o'
+ optype = ip_ptype (IO_TYPE(op), IO_NBYTES(op))
+ switch (optype) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ O_LEN(o) = IO_NPIX(op)
+ O_TYPE(o) = TY_SHORT
+ call malloc (O_VALP(o), IO_NPIX(op), TY_SHORT)
+ call amovs (Mems[IO_DATA(op)], Mems[O_VALP(o)], IO_NPIX(op))
+ $for (ilrd)
+ case TY_PIXEL:
+ O_LEN(o) = IO_NPIX(op)
+ O_TYPE(o) = TY_PIXEL
+ call malloc (O_VALP(o), IO_NPIX(op), TY_PIXEL)
+ call amov$t (Mem$t[IO_DATA(op)], Mem$t[O_VALP(o)], IO_NPIX(op))
+ $endfor
+ }
+
+ } else {
+ call smark (sp)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+ call sprintf (Memc[buf], SZ_LINE, "Unknown outbands operand `%s'\n")
+ call pargstr(opname)
+ call sfree (sp)
+ call error (1, Memc[buf])
+ }
+end
+
+
+# IP_EVALUATE -- Evaluate the outbands expression.
+
+pointer procedure ip_evaluate (ip, expr)
+
+pointer ip #i task struct pointer
+char expr[ARB] #i expression to be evaluated
+
+pointer o # operand pointer to result
+
+int locpr()
+pointer evvexpr()
+extern ip_getop(), ip_obfcn()
+errchk evvexpr
+
+begin
+ if (DEBUG) { call eprintf("ip_eval: expr='%s'\n") ; call pargstr(expr) }
+
+ # Evaluate the expression.
+ iferr {
+ o = evvexpr (expr, locpr(ip_getop), ip, locpr(ip_obfcn), ip,
+ EV_RNGCHK)
+ } then
+ call erract (EA_FATAL)
+
+ return (o)
+end
+
+
+# IP_OBFCN -- Called by evvexpr to execute import outbands special functions.
+
+procedure ip_obfcn (ip, fcn, args, nargs, o)
+
+pointer ip #i task struct pointer
+char fcn[ARB] #i function to be executed
+pointer args[ARB] #i argument list
+int nargs #i number of arguments
+pointer o #o operand pointer
+
+pointer sp, buf
+pointer r, g, b, gray, color, cmap
+int i, len, v_nargs, func
+
+int or(), strdic()
+bool strne()
+
+define setop_ 99
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_FNAME, TY_CHAR)
+
+ # Lookup function in dictionary.
+ func = strdic (fcn, Memc[buf], SZ_LINE, OB_FUNCTIONS)
+ if (func > 0 && strne(fcn,Memc[buf]))
+ func = 0
+
+ # Abort if the function is not known.
+ if (func <= 0)
+ call xev_error1 ("unknown function `%s' called", fcn)
+
+ # Verify the correct number of arguments, negative value means a
+ # variable number of args, handle it in the evaluation.
+ switch (func) {
+ case GRAY, GREY:
+ v_nargs = 3
+ case FLIPX, FLIPY:
+ v_nargs = 1
+ case RED, GREEN, BLUE:
+ v_nargs = 1
+ }
+ if (v_nargs > 0 && nargs != v_nargs)
+ call xev_error2 ("function `%s' requires %d arguments",
+ fcn, v_nargs)
+ else if (v_nargs < 0 && nargs < abs(v_nargs))
+ call xev_error2 ("function `%s' requires at least %d arguments",
+ fcn, abs(v_nargs))
+
+ if (DEBUG) {
+ call eprintf ("obfcn: nargs=%d func=%d\n")
+ call pargi (nargs) ; call pargi (func)
+ do i = 1, nargs { call eprintf ("\t") ; call zzi_pevop (args[i]) }
+ call flush (STDERR)
+ }
+
+ # Evaluate the function.
+ switch (func) {
+ case GRAY, GREY:
+ # evaluate expression for NTSC grayscale.
+ r = O_VALP(args[1])
+ g = O_VALP(args[2])
+ b = O_VALP(args[3])
+ len = O_LEN(args[1]) - 1
+ O_LEN(o) = len + 1
+ O_TYPE(o) = TY_REAL
+ call malloc (O_VALP(o), len+1, TY_REAL)
+ gray = O_VALP(o)
+ switch (O_TYPE(args[1])) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ do i = 0, len {
+ Memr[gray+i] = R_COEFF * Mems[r+i] +
+ G_COEFF * Mems[g+i] +
+ B_COEFF * Mems[b+i]
+ }
+ $for (ilrd)
+ case TY_PIXEL:
+ do i = 0, len {
+ Memr[gray+i] = R_COEFF * Mem$t[r+i] +
+ G_COEFF * Mem$t[g+i] +
+ B_COEFF * Mem$t[b+i]
+ }
+ $endfor
+ }
+
+ case RED:
+ # Get the red colormap component of the image.
+ cmap = IP_CMAP(ip)
+ if (func <= 0)
+ call xev_error1 ("No colormap in image for function `%s'", fcn)
+ r = O_VALP(args[1])
+ len = O_LEN(args[1]) - 1
+ O_LEN(o) = len + 1
+ O_TYPE(o) = TY_SHORT
+ call malloc (O_VALP(o), len+1, TY_SHORT)
+ color = O_VALP(o)
+ switch (O_TYPE(args[1])) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_RED,Mems[r+i]+1)
+ $for (il)
+ case TY_PIXEL:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_RED,Mem$t[r+i]+1)
+ $endfor
+ }
+
+ case GREEN:
+ # Get the blue colormap component of the image.
+ cmap = IP_CMAP(ip)
+ if (func <= 0)
+ call xev_error1 ("No colormap in image for function `%s'", fcn)
+ g = O_VALP(args[1])
+ len = O_LEN(args[1]) - 1
+ O_LEN(o) = len + 1
+ O_TYPE(o) = TY_SHORT
+ call malloc (O_VALP(o), len+1, TY_SHORT)
+ color = O_VALP(o)
+ switch (O_TYPE(args[1])) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_GREEN,Mems[g+i]+1)
+ $for (il)
+ case TY_PIXEL:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_GREEN,char(Mem$t[g+i]+1))
+ $endfor
+ }
+
+ case BLUE:
+ # Get the blue colormap component of the image.
+ cmap = IP_CMAP(ip)
+ if (func <= 0)
+ call xev_error1 ("No colormap in image for function `%s'", fcn)
+ b = O_VALP(args[1])
+ len = O_LEN(args[1]) - 1
+ O_LEN(o) = len + 1
+ O_TYPE(o) = TY_SHORT
+ call malloc (O_VALP(o), len+1, TY_SHORT)
+ color = O_VALP(o)
+ switch (O_TYPE(args[1])) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_BLUE,Mems[b+i]+1)
+ $for (il)
+ case TY_PIXEL:
+ do i = 0, len
+ Mems[color+i] = CMAP(cmap,IP_BLUE,char(Mem$t[b+i]+1))
+ $endfor
+ }
+
+ case FLIPX:
+ # Set flag to reverse pixel order on output.
+ IP_FLIP(ip) = or (IP_FLIP(ip), FLIP_X)
+ goto setop_
+
+ case FLIPY:
+ # Set flag to write image from bottom to top.
+ IP_FLIP(ip) = or (IP_FLIP(ip), FLIP_Y)
+
+ # Copy argument operand descriptor to 'o'
+setop_ switch (O_TYPE(args[1])) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ O_LEN(o) = O_LEN(args[1])
+ O_TYPE(o) = TY_SHORT
+ call malloc (O_VALP(o), O_LEN(args[1]), TY_SHORT)
+ call amovs (Mems[O_VALP(ARGS[1])], Mems[O_VALP(o)], O_LEN(o))
+ $for (ilrd)
+ case TY_PIXEL:
+ O_LEN(o) = O_LEN(args[1])
+ O_TYPE(o) = TY_PIXEL
+ call malloc (O_VALP(o), O_LEN(args[1]), TY_PIXEL)
+ call amov$t (Mem$t[O_VALP(args[1])], Mem$t[O_VALP(o)], O_LEN(o))
+ $endfor
+ }
+
+ }
+
+ if (DEBUG) { call zzi_pevop (o) }
+
+ call sfree (sp)
+end
diff --git a/pkg/dataio/import/ipproc.gx b/pkg/dataio/import/ipproc.gx
new file mode 100644
index 00000000..38217a4d
--- /dev/null
+++ b/pkg/dataio/import/ipproc.gx
@@ -0,0 +1,804 @@
+include <mach.h>
+include <imhdr.h>
+include <evvexpr.h>
+include "../import.h"
+
+define DEBUG false
+
+
+# IP_PRBAND -- Process a band interleaved file.
+
+procedure ip_prband (ip, fd, im, cmap)
+
+pointer ip #i task struct pointer
+int fd #i inpout file descriptor
+pointer im #i output image pointer
+pointer cmap #i colormap pointer
+
+int i, j, nlines, npix
+int optype, nbytes_pix, percent
+int cur_offset, band_offset, line_offset
+
+int ip_ptype()
+long ip_lnote()
+
+begin
+ # Rewind the file and skip header pixels.
+ call ip_lseek (fd, BOF)
+ call ip_lseek (fd, IP_HSKIP(ip)+1)
+
+ # Compute the offset between the same pixel in different bands. This
+ # is the area of the image plus any image padding, computed as a
+ # byte offset.
+ optype = ip_ptype (IO_TYPE(PTYPE(ip,1)),IO_NBYTES(PTYPE(ip,1)))
+ switch (optype) {
+ case TY_UBYTE: nbytes_pix = 1
+ case TY_USHORT, TY_SHORT: nbytes_pix = SZB_CHAR * SZ_SHORT
+ case TY_INT: nbytes_pix = SZB_CHAR * SZ_INT32
+ case TY_LONG: nbytes_pix = SZB_CHAR * SZ_LONG
+ case TY_REAL: nbytes_pix = SZB_CHAR * SZ_REAL
+ case TY_DOUBLE: nbytes_pix = SZB_CHAR * SZ_DOUBLE
+ }
+ band_offset = (IP_AXLEN(ip,1) * (IP_AXLEN(ip,2)-1)) +
+ ((IP_LSKIP(ip) + IP_LPAD(ip)) * (IP_AXLEN(ip,2)-1)) +
+ IP_BSKIP(ip)
+ band_offset = (band_offset * nbytes_pix) #+ 1
+
+ if (DEBUG) {
+ call eprintf ("ip_prband: band_offset=%d curpos=%d\n")
+ call pargi(band_offset) ; call pargi(ip_lnote(fd))
+ call zzi_prstruct ("ip_prband", ip)
+ }
+
+ # Patch up the pixtype param if needed.
+ call ip_fix_pixtype (ip)
+
+ # See if we need to create any outbands operands if the user didn't.
+ if (IP_NBANDS(ip) == ERR)
+ call ip_fix_outbands (ip)
+
+ # Loop over the image lines.
+ nlines = IP_AXLEN(ip,2)
+ npix = IP_AXLEN(ip,1)
+ percent = 0
+ do i = 1, nlines {
+ # Skip pixels at front of line
+ line_offset = ip_lnote (fd)
+ if (IP_LSKIP(ip) != 0)
+ call ip_lskip (fd, IP_LSKIP(ip))
+
+ # Read pixels in the line and save as operand.
+ call ip_rdline (ip, fd, 1, npix, cmap)
+
+ # Skip pixels at end of line.
+ if (IP_LPAD(ip) != 0)
+ call ip_lskip (fd, IP_LPAD(ip))
+ cur_offset = ip_lnote (fd)
+
+ # Loop over each of the remaining pixtypes.
+ do j = 2, IP_NPIXT(ip) {
+ # Seek to offset of next band (i.e. line_offset + band_offset).
+ call ip_lskip (fd, band_offset)
+ if (IP_LSKIP(ip) != 0)
+ call ip_lskip (fd, IP_LSKIP(ip))
+ call ip_rdline (ip, fd, j, npix, cmap) # read pixels in the line
+ if (IP_LPAD(ip) != 0)
+ call ip_lskip (fd, IP_LPAD(ip))
+ }
+
+ # Evaluate and write the outbands expressions.
+ call ip_probexpr (ip, im, npix, i)
+
+ # Print percent done if being verbose
+ #if (IP_VERBOSE(ip) == YES)
+ call ip_pstat (ip, i, percent)
+
+ # Restore file pointer to cur_offset.
+ call ip_lseek (fd, cur_offset)
+ }
+ do i = 1, IP_NBANDS(ip)
+ call mfree (BUFFER(ip,i), IM_PIXTYPE(im))
+end
+
+
+# IP_PRLINE -- Process a line interleaved file.
+
+procedure ip_prline (ip, fd, im, cmap)
+
+pointer ip #i task struct pointer
+int fd #i inpout file descriptor
+pointer im #i output image pointer
+pointer cmap #i colormap pointer
+
+int i, j, nlines, npix, percent
+
+begin
+ # Rewind the file and skip header pixels.
+ call ip_lseek (fd, BOF)
+ call ip_lseek (fd, IP_HSKIP(ip)+1)
+
+ if (DEBUG) {
+ call eprintf ("ip_prline:\n")
+ call zzi_prstruct ("ip_prline", ip)
+ }
+
+ # Patch up the pixtype param if needed.
+ call ip_fix_pixtype (ip)
+
+ # See if we need to create any outbands operands if the user didn't.
+ if (IP_NBANDS(ip) == ERR)
+ call ip_fix_outbands (ip)
+
+ # Loop over the image lines.
+ nlines = IP_AXLEN(ip,2)
+ npix = IP_AXLEN(ip,1)
+ percent = 0
+ do i = 1, nlines {
+
+ do j = 1, IP_NPIXT(ip) {
+ # Skip pixels at front of line
+ call ip_lskip (fd, IP_LSKIP(ip))
+
+ # Read pixels in the line and save as operand.
+ call ip_rdline (ip, fd, j, npix, cmap)
+
+ # Skip pixels at end of line.
+ call ip_lskip (fd, IP_LPAD(ip))
+ }
+
+ # Evaluate and write the outbands expressions.
+ call ip_probexpr (ip, im, npix, i)
+
+ # Print percent done if being verbose
+ #if (IP_VERBOSE(ip) == YES)
+ call ip_pstat (ip, i, percent)
+ }
+ do i = 1, IP_NBANDS(ip)
+ call mfree (BUFFER(ip,i), IM_PIXTYPE(im))
+end
+
+
+# IP_PRPIX -- Process a pixel interleaved file.
+
+procedure ip_prpix (ip, fd, im, cmap)
+
+pointer ip #i task struct pointer
+int fd #i inpout file descriptor
+pointer im #i output image pointer
+pointer cmap #i colormap pointer
+
+pointer op, data
+int i, swap, optype, nlines
+int percent, npix, totpix
+
+int and(), ip_ptype()
+
+begin
+ # Rewind the file and skip header pixels.
+ call ip_lseek (fd, BOF)
+ call ip_lseek (fd, IP_HSKIP(ip)+1)
+
+ if (DEBUG) { call eprintf ("ip_prpix: ") }
+
+ # See if we need to create any outbands operands if the user didn't.
+ if (IP_NBANDS(ip) == ERR)
+ call ip_fix_outbands (ip)
+
+ # Allocate the pixtype data pointers.
+ npix = IP_AXLEN(ip,1)
+ nlines = IP_NPIXT(ip)
+ do i = 1, nlines {
+ op = PTYPE(ip,i)
+ optype = ip_ptype (IO_TYPE(op),IO_NBYTES(op))
+ IO_NPIX(op) = npix
+ if (IO_DATA(op) == NULL)
+ if (optype == TY_UBYTE)
+ call malloc (IO_DATA(op), npix, TY_SHORT)
+ else
+ call malloc (IO_DATA(op), npix, optype)
+ }
+
+ # Loop over the image lines.
+ nlines = IP_AXLEN(ip,2)
+ totpix = npix * IP_NPIXT(ip)
+ swap = IP_SWAP(ip)
+ percent = 0
+ if (DEBUG) {
+ call zzi_prstruct ("ip_prpix", ip)
+ call eprintf ("nl=%d np=%d tp=%d:\n")
+ call pargi(nlines) ; call pargi(npix) ; call pargi(totpix)
+ }
+ do i = 1, nlines {
+
+ # Skip pixels at front of line
+ call ip_lskip (fd, IP_LSKIP(ip))
+
+ # Read pixels in the line.
+ switch (optype) {
+ case TY_UBYTE:
+ call ip_agetb (fd, data, totpix)
+ call ip_lskip (fd, totpix)
+ # Apply a colormap to the bytes. In general a pixel-interleaved
+ # file is a 24-bit True Color image, but maybe this is a
+ # 3-D color index file?
+ if (cmap != NULL && IP_USE_CMAP(ip) == YES)
+ call ip_gray_cmap (Memc[data], totpix, cmap)
+
+ case TY_USHORT:
+ call ip_agetu (fd, data, totpix)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2) {
+ call bswap2 (Mems[data], 1, Mems[data], 1,
+ (totpix*(SZ_SHORT*SZB_CHAR)))
+ }
+ call ip_lskip (fd, (totpix * (SZB_CHAR * SZ_SHORT)))
+
+ $for (silrd)
+ case TY_PIXEL:
+ call ip_aget$t (fd, data, totpix)
+ $if (datatype == s)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2) {
+ call bswap2 (Mem$t[data], 1, Mem$t[data], 1,
+ (totpix*(SZ_PIXEL*SZB_CHAR)))
+ }
+ $endif
+ $if (datatype == il)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I4) == S_I4) {
+ if (SZ_INT != SZ_INT32) {
+ call ipak32 (Mem$t[data], Mem$t[data], totpix)
+ call bswap4 (Mem$t[data], 1, Mem$t[data], 1,
+ (totpix*(SZ_INT32*SZB_CHAR)))
+ } else {
+ call bswap4 (Mem$t[data], 1, Mem$t[data], 1,
+ (totpix*(SZ_INT*SZB_CHAR)))
+ }
+ }
+ $endif
+ $if (datatype == r)
+ if (and(swap, S_ALL) == S_ALL) {
+ call bswap4 (Mem$t[data], 1, Mem$t[data], 1,
+ (totpix*(SZ_PIXEL*SZB_CHAR)))
+ }
+ $endif
+ $if (datatype == d)
+ if (and(swap, S_ALL) == S_ALL) {
+ call bswap8 (Mem$t[data], 1, Mem$t[data], 1,
+ (totpix*(SZ_PIXEL*SZB_CHAR)))
+ }
+ $endif
+
+ $if (datatype == il)
+ call ip_lskip (fd, (totpix * (SZB_CHAR * SZ_INT32)))
+ $else
+ call ip_lskip (fd, (totpix * (SZB_CHAR * SZ_PIXEL)))
+ $endif
+ $endfor
+ }
+
+ # Skip pixels at end of line.
+ call ip_lskip (fd, IP_LPAD(ip))
+
+ # Separate pixels into different vectors.
+ call ip_upkpix (ip, data, npix)
+
+ # Evaluate and write the outbands expressions.
+ call ip_probexpr (ip, im, npix, i)
+
+ # Print percent done if being verbose
+ #if (IP_VERBOSE(ip) == YES)
+ call ip_pstat (ip, i, percent)
+ }
+
+ if (optype == TY_UBYTE)
+ call mfree (data, TY_SHORT)
+ else
+ call mfree (data, optype)
+ do i = 1, IP_NBANDS(ip)
+ call mfree (BUFFER(ip,i), IM_PIXTYPE(im))
+end
+
+
+# IP_PROBEXPR -- Process each of the outbands expressions and write the result
+# to the output image.
+
+procedure ip_probexpr (ip, im, npix, line)
+
+pointer ip #i task struct pointer
+pointer im #i output image pointer
+int npix #i number of output pixels
+int line #i line number
+
+int i
+pointer out, ip_evaluate()
+
+begin
+ # Loop over outbands expressions.
+ do i = 1, IP_NBANDS(ip) {
+ # Evaluate outbands expression.
+ out = ip_evaluate (ip, O_EXPR(ip,i))
+
+ # Write bands to output image
+ if (IP_OUTPUT(ip) != IP_NONE)
+ call ip_wrline (ip, im, out, npix, line, i)
+
+ call evvfree (out)
+ }
+end
+
+
+# IP_RDLINE -- Read a line of pixels from the binary file.
+
+procedure ip_rdline (ip, fd, pnum, npix, cmap)
+
+pointer ip #i task struct pointer
+int fd #i input file descriptor
+int pnum #i pixtype number
+int npix #i number of pixels to read
+pointer cmap #i colormap pointer
+
+pointer op, data
+int swap, ptype
+
+int and(), ip_ptype()
+
+begin
+ # Read pixels in the line and save as operand.
+ op = PTYPE(ip,pnum)
+ ptype = ip_ptype (IO_TYPE(op), IO_NBYTES(op))
+ data = IO_DATA(op)
+ swap = IP_SWAP(ip)
+ IO_NPIX(op) = npix
+
+ switch (ptype) {
+ case TY_UBYTE:
+ call ip_agetb (fd, data, npix)
+ call ip_lskip (fd, npix)
+ # Apply a colormap to the bytes. If the colormap is non-null we
+ # assume the bytes are color indices into a colormap.
+ if (cmap != NULL && IP_USE_CMAP(ip) == YES)
+ call ip_gray_cmap (Memc[data], npix, cmap)
+
+ case TY_USHORT:
+ call ip_agetu (fd, data, npix)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2) {
+ call bswap2 (Mems[data], 1, Mems[data], 1,
+ (npix*(SZ_SHORT*SZB_CHAR)))
+ }
+ call ip_lskip (fd, (npix * (SZB_CHAR * SZ_SHORT)))
+ $for (silrd)
+ case TY_PIXEL:
+ call ip_aget$t (fd, data, npix)
+ $if (datatype == s)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I2) {
+ call bswap2 (Mems[data], 1, Mems[data], 1,
+ (npix*(SZ_PIXEL*SZB_CHAR)))
+ }
+ $endif
+ $if (datatype == il)
+ if (and(swap, S_ALL) == S_ALL || and(swap, S_I2) == S_I4) {
+ if (SZ_INT != SZ_INT32) {
+ call ipak32 (Mem$t[data], Mem$t[data], npix)
+ call bswap4 (Mem$t[data], 1, Mem$t[data], 1,
+ (npix*(SZ_INT32*SZB_CHAR)))
+ } else {
+ call bswap4 (Mem$t[data], 1, Mem$t[data], 1,
+ (npix*(SZ_PIXEL*SZB_CHAR)))
+ }
+ }
+ $endif
+ $if (datatype == r)
+ if (and(swap, S_ALL) == S_ALL) {
+ call bswap4 (Mem$t[data], 1, Mem$t[data], 1,
+ (npix*(SZ_PIXEL*SZB_CHAR)))
+ }
+ $endif
+ $if (datatype == d)
+ if (and(swap, S_ALL) == S_ALL) {
+ call bswap8 (Mem$t[data], 1, Mem$t[data], 1,
+ (npix*(SZ_PIXEL*SZB_CHAR)))
+ }
+ $endif
+
+ $if (datatype == il)
+ call ip_lskip (fd, npix * (SZB_CHAR * SZ_INT32))
+ $else
+ call ip_lskip (fd, npix * (SZB_CHAR * SZ_PIXEL))
+ $endif
+ $endfor
+ }
+ IO_DATA(op) = data
+end
+
+
+# IP_WRLINE -- Write a line of pixels to the output image. We handle image
+# flipping here to avoid possibly doing it several times while the outbands
+# expression is being evaluated.
+
+procedure ip_wrline (ip, im, out, npix, line, band)
+
+pointer ip #i task struct pointer
+pointer im #i output image pointer
+pointer out #i output operand pointer
+int npix #i number of pixels to read
+int line #i image line number
+int band #i image band number
+
+int i, lnum, type
+int nldone, blnum
+pointer sp, dptr, data, optr
+bool lastline
+
+int and()
+pointer imps3s(), imps3i(), imps3l(), imps3r(), imps3d()
+pointer ip_chtype()
+
+data blnum /0/
+data nldone /1/
+data lastline /false/
+
+begin
+ call smark (sp)
+
+ # The first thing we do is change the datatype of the operand to
+ # match the output pixel type.
+ if (IP_OUTTYPE(ip) != NULL) {
+ if (IP_OUTTYPE(ip) == O_TYPE(out))
+ optr = O_VALP(out)
+ else
+ optr = ip_chtype (out, IP_OUTTYPE(ip))
+ }
+ type = IP_OUTTYPE(ip)
+
+ # See if we're flipping image in Y, and adjust the line number.
+ if (and(IP_FLIP(ip),FLIP_Y) == FLIP_Y) {
+ lnum = IP_AXLEN(ip,2) - line + 1
+ if (band == 1)
+ blnum = IP_SZBUF(ip) - mod (line-1, IP_SZBUF(ip))
+ lastline = (lnum == 1)
+ } else {
+ lnum = line
+ if (band == 1)
+ blnum = blnum + 1
+ lastline = (lnum == IP_AXLEN(ip,2))
+ }
+
+ # See if we're flipping image in x, and reverse the pixels.
+ if (and(IP_FLIP(ip),FLIP_X) == FLIP_X) {
+ call salloc (dptr, npix, type)
+ do i = 1, npix {
+ switch (type) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ Mems[dptr+i-1] = Mems[optr+(npix-i)]
+ $for (ilrd)
+ case TY_PIXEL:
+ Mem$t[dptr+i-1] = Mem$t[optr+(npix-i)]
+ $endfor
+ }
+ }
+ } else
+ dptr = optr
+
+ # Make sure the image pixtype is set.
+ if (IM_PIXTYPE(im) == NULL)
+ IM_PIXTYPE(im) = type
+
+ # Allocate the buffer pointer if needed.
+ if (BUFFER(ip,band) == NULL)
+ call calloc (BUFFER(ip,band), npix*IP_SZBUF(ip), IP_OUTTYPE(ip))
+
+ if (nldone < IP_SZBUF(ip) && !lastline) {
+ # Copy the image line to the buffer
+ data = BUFFER(ip,band)
+ switch (type) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ call amovs (Mems[dptr], Mems[data+((blnum-1)*npix)], npix)
+ $for (ilrd)
+ case TY_PIXEL:
+ call amov$t (Mem$t[dptr], Mem$t[data+((blnum-1)*npix)], npix)
+ $endfor
+ }
+ if (band == IP_NBANDS(ip))
+ nldone = nldone + 1
+
+ } else {
+ # Write the buffer to the image as a section.
+ data = BUFFER(ip,band)
+ switch (type) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ call amovs (Mems[dptr], Mems[data+((blnum-1)*npix)], npix)
+ if (and(IP_FLIP(ip),FLIP_Y) == FLIP_Y) {
+ data = imps3s (im, 1, npix,
+ max(1,(lnum-IP_SZBUF(ip)+1)+IP_SZBUF(ip)-1),
+ max(1,lnum+min(nldone,IP_SZBUF(ip))-1),
+ band, band)
+ call amovs (Mems[BUFFER(ip,band)+(blnum-1)*npix],
+ Mems[data], npix*(IP_SZBUF(ip)-blnum+1))
+ } else {
+ data = imps3s (im, 1, npix,
+ min(IP_AXLEN(ip,2),(lnum-blnum+1)),
+ min(IP_AXLEN(ip,2),lnum),
+ band, band)
+ call amovs (Mems[BUFFER(ip,band)], Mems[data], npix*blnum)
+ }
+ $for (ilrd)
+ case TY_PIXEL:
+ call amov$t (Mem$t[dptr], Mem$t[data+((blnum-1)*npix)], npix)
+ if (and(IP_FLIP(ip),FLIP_Y) == FLIP_Y) {
+ data = imps3$t (im, 1, npix,
+ max(1,(lnum-IP_SZBUF(ip)+1)+IP_SZBUF(ip)-1),
+ max(1,lnum+min(nldone,IP_SZBUF(ip))-1),
+ band, band)
+ call amov$t (Mem$t[BUFFER(ip,band)+(blnum-1)*npix],
+ Mem$t[data], npix*(IP_SZBUF(ip)-blnum+1))
+ } else {
+ data = imps3$t (im, 1, npix,
+ min(IP_AXLEN(ip,2),(lnum-blnum+1)),
+ min(IP_AXLEN(ip,2),lnum),
+ band, band)
+ call amov$t (Mem$t[BUFFER(ip,band)], Mem$t[data],
+ npix*blnum)
+ }
+ $endfor
+ }
+ if (band == IP_NBANDS(ip)) {
+ nldone = 1
+ blnum = 0
+ }
+ }
+
+ if (IP_OUTTYPE(ip) != O_TYPE(out))
+ call mfree (optr, type)
+ call sfree (sp)
+end
+
+
+# IP_UPKPIX -- Unpack a line of pixel-interleaved pixels to the separate
+# pixtype operand arrays.
+
+procedure ip_upkpix (ip, ptr, npix)
+
+pointer ip #i task struct pointer
+pointer ptr #i pointer to pixels
+int npix #i number of pixels in line
+
+pointer op[IM_MAXDIM]
+int i, j, np, optype[IM_MAXDIM]
+
+int ip_ptype()
+
+begin
+ np = IP_NPIXT(ip)
+ do j = 1, np {
+ op[j] = PTYPE(ip,j)
+ optype[j] = ip_ptype (IO_TYPE(op[j]),IO_NBYTES(op[j]))
+ }
+
+ do j = 1, np {
+
+ do i = 0, npix-1 {
+ switch (optype[j]) {
+ case TY_UBYTE, TY_USHORT, TY_SHORT:
+ Mems[IO_DATA(op[j])+i] = Mems[ptr+(i*np+j)-1]
+ $for (ilrd)
+ case TY_PIXEL:
+ Mem$t[IO_DATA(op[j])+i] = Mem$t[ptr+(i*np+j)-1]
+ $endfor
+ }
+ }
+ }
+end
+
+
+# IP_FIX_PIXTYPE -- Create the pixtype operands for 3-D band or line-
+# interleaved files. These weren't allocated at first since the pixtype
+# parameter or database field was atomic.
+
+procedure ip_fix_pixtype (ip)
+
+pointer ip #i task struct pointer
+
+pointer op, op1
+int i, nnp
+
+begin
+ if (DEBUG) {
+ call eprintf ("fix_pixtype: npixt=%d ndim=%d inter=%d\n")
+ call pargi(IP_NPIXT(ip)) ; call pargi(IP_NDIM(ip))
+ call pargi(IP_INTERLEAVE(ip)) ; call flush (STDERR)
+ }
+
+ # See if there's anything to be fixed.
+ if (IP_NDIM(ip) < 3 || IP_NDIM(ip) < IP_NPIXT(ip))
+ return
+ if (BAND_INTERLEAVED(ip) && (IP_NPIXT(ip) == IP_NDIM(ip)))
+ return
+ if (LINE_INTERLEAVED(ip) && (IP_NPIXT(ip) == IP_INTERLEAVE(ip)))
+ return
+
+ if (LINE_INTERLEAVED(ip))
+ nnp = IP_INTERLEAVE(ip)
+ else
+ #nnp = IP_NDIM(ip)
+ nnp = IP_AXLEN(ip,3)
+
+ # Make the new pixtype operands.
+ op1 = PTYPE(ip,1)
+ do i = 2, nnp {
+ call ip_alloc_operand (PTYPE(ip,i))
+ op = PTYPE(ip,i)
+ IO_TYPE(op) = IO_TYPE(op1)
+ IO_NBYTES(op) = IO_NBYTES(op1)
+ call sprintf (OP_TAG(op), SZ_TAG, "b%d")
+ call pargi (i)
+ }
+ IP_NPIXT(ip) = nnp
+
+ if (DEBUG) { call zzi_prstruct ("fix_pixtype", ip) }
+end
+
+
+# IP_FIX_OUTBANDS -- Create the outbands operands if none were specified in
+# the parameter file.
+
+procedure ip_fix_outbands (ip)
+
+pointer ip #i task struct pointer
+
+pointer sp, buf
+pointer im
+int i, nbands
+
+define SZ_OBSTR 2500
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_FNAME, TY_CHAR)
+
+ if (DEBUG) {
+ call eprintf ("fix_outbands: npixt=%d ndim=%d inter=%d\n")
+ call pargi(IP_NPIXT(ip)) ; call pargi(IP_NDIM(ip))
+ call pargi(IP_INTERLEAVE(ip)) ; call flush (STDERR)
+ }
+
+ # Free up the existing outbands operands.
+ nbands = IP_NBANDS(ip)
+ do i = 1, nbands
+ call ip_free_outbands (OBANDS(ip,i))
+
+ # Create an outbands parameter string according to the tags in the
+ # pixtype structure. This way we preserve any user-defined tags on
+ # output.
+ nbands = IP_NPIXT(ip)
+ call aclrc (Memc[buf], SZ_FNAME)
+ do i = 1, nbands {
+ call ip_alloc_outbands (OBANDS(ip,i))
+ call aclrc (Memc[buf], SZ_FNAME)
+ call sprintf (Memc[buf], SZ_FNAME, "b%d")
+ call pargi (i)
+ call strcpy (Memc[buf], O_EXPR(ip,i), SZ_EXPR)
+
+ # Load the operand struct.
+ call strcpy (Memc[buf], OP_TAG(O_OP(ip,i)), SZ_EXPR)
+ }
+ IP_NBANDS(ip) = nbands
+
+ # Fix the output image dimensions.
+ im = IP_IM(ip)
+ IM_LEN(im,3) = IP_AXLEN(ip,3)
+ if (IP_NBANDS(ip) > 1)
+ IM_NDIM(im) = 3
+ else
+ IM_NDIM(im) = IP_NDIM(ip)
+
+ call sfree (sp)
+
+ if (DEBUG) { call zzi_prstruct ("fix_outbands", ip) }
+end
+
+
+# IP_CHTYPE - Change the expression operand vector to the output datatype.
+# We allocate and return a pointer to the correct type to the converted
+# pixels, this pointer must be freed later on.
+
+pointer procedure ip_chtype (op, type)
+
+pointer op #i evvexpr operand pointer
+int type #i new type of pointer
+
+pointer out, coerce()
+
+begin
+ # Allocate the pointer and coerce it so the routine works.
+ if (type == TY_UBYTE || type == TY_CHAR)
+ call calloc (out, O_LEN(op), TY_CHAR)
+ else {
+ call calloc (out, O_LEN(op), type)
+ out = coerce (out, type, TY_CHAR)
+ }
+
+ # Change the pixel type.
+ switch (O_TYPE(op)) {
+ case TY_CHAR:
+ call achtc (Memc[O_VALP(op)], Memc[out], O_LEN(op), type)
+ case TY_SHORT:
+ call achts (Mems[O_VALP(op)], Memc[out], O_LEN(op), type)
+ case TY_INT:
+ call achti (Memi[O_VALP(op)], Memc[out], O_LEN(op), type)
+ case TY_LONG:
+ call achtl (Meml[O_VALP(op)], Memc[out], O_LEN(op), type)
+ case TY_REAL:
+ call achtr (Memr[O_VALP(op)], Memc[out], O_LEN(op), type)
+ case TY_DOUBLE:
+ call achtd (Memd[O_VALP(op)], Memc[out], O_LEN(op), type)
+ default:
+ call error (0, "Invalid output type requested.")
+ }
+
+ out = coerce (out, TY_CHAR, type)
+ return (out)
+end
+
+
+define NTYPES 6
+define NBITPIX 4
+
+# IP_PTYPE -- For a given pixtype parameter return the corresponding IRAF
+# data type.
+
+int procedure ip_ptype (type, nbytes)
+
+int type #i pixel type
+int nbytes #i number of bytes
+
+int i, pt, pb, ptype
+int tindex[NTYPES], bindex[NBITPIX], ttbl[NTYPES*NBITPIX]
+
+data tindex /PT_BYTE, PT_UINT, PT_INT, PT_IEEE, PT_NATIVE, PT_SKIP/
+data bindex /1, 2, 4, 8/
+
+data (ttbl(i), i= 1, 4) /TY_UBYTE, TY_USHORT, TY_INT, 0/ # B
+data (ttbl(i), i= 5, 8) /TY_UBYTE, TY_USHORT, 0, 0/ # U
+data (ttbl(i), i= 9,12) /TY_UBYTE, TY_SHORT, TY_INT, 0/ # I
+data (ttbl(i), i=13,16) / 0, 0, TY_REAL, TY_DOUBLE/ # R
+data (ttbl(i), i=17,20) / 0, 0, TY_REAL, TY_DOUBLE/ # N
+data (ttbl(i), i=21,24) /TY_UBYTE, TY_USHORT, TY_REAL, TY_DOUBLE/ # X
+
+begin
+ if (type == 0 || nbytes == 0) # uninitialized values
+ return (0)
+
+ pt = NTYPES
+ do i = 1, NTYPES {
+ if (tindex[i] == type)
+ pt = i
+ }
+ pb = NBITPIX
+ do i = 1, NBITPIX {
+ if (bindex[i] == nbytes)
+ pb = i
+ }
+
+ ptype = ttbl[(pt-1)*NBITPIX+pb]
+ if (ptype == 0)
+ call error (0, "Invalid pixtype specified.")
+ else
+ return (ptype)
+end
+
+
+# IP_PSTAT - Print information about the progress we're making.
+
+procedure ip_pstat (ip, row, percent)
+
+pointer ip #i task struct pointer
+int row #u current row
+int percent #u percent completed
+
+begin
+ # Print percent done if being verbose
+ if (row * 100 / IP_AXLEN(ip,2) >= percent + 10) {
+ percent = percent + 10
+ call eprintf (" Status: %2d%% complete\r")
+ call pargi (percent)
+ call flush (STDERR)
+ }
+end
diff --git a/pkg/dataio/import/mkpkg b/pkg/dataio/import/mkpkg
new file mode 100644
index 00000000..c12f77f6
--- /dev/null
+++ b/pkg/dataio/import/mkpkg
@@ -0,0 +1,37 @@
+# MKPKG file for the IMPORT task
+
+$call update
+$exit
+
+update:
+ $checkout libpkg.a ../
+ $update libpkg.a
+ $checkin libpkg.a ../
+ ;
+
+generic:
+ $set GEN = "$$generic -k"
+
+ $ifolder (generic/ipdb.x, ipdb.gx)
+ $(GEN) ipdb.gx -o generic/ipdb.x $endif
+ $ifolder (generic/ipfio.x, ipfio.gx)
+ $(GEN) ipfio.gx -o generic/ipfio.x $endif
+ $ifolder (generic/ipobands.x, ipobands.gx)
+ $(GEN) ipobands.gx -o generic/ipobands.x $endif
+ $ifolder (generic/ipproc.x, ipproc.gx)
+ $(GEN) ipproc.gx -o generic/ipproc.x $endif
+ ;
+
+libpkg.a:
+ $ifeq (USE_GENERIC, yes) $call generic $endif
+ @generic
+ @bltins
+
+ fmtdb.x import.h <ctotok.h> <error.h> <evvexpr.h> <fset.h>
+ ipbuiltin.x import.h
+ ipinfo.x import.h
+ iplistpix.x <imhdr.h> <error.h> <mwset.h>
+ ipmkhdr.x import.h <ctype.h> <imhdr.h>
+ t_import.x import.h <ctype.h> <error.h> <evvexpr.h> <imhdr.h>
+ zzidbg.x import.h <evvexpr.h>
+ ;
diff --git a/pkg/dataio/import/t_import.x b/pkg/dataio/import/t_import.x
new file mode 100644
index 00000000..adb37d17
--- /dev/null
+++ b/pkg/dataio/import/t_import.x
@@ -0,0 +1,768 @@
+include <error.h>
+include <ctype.h>
+include <evvexpr.h>
+include <imhdr.h>
+include "import.h"
+
+define DEBUG false
+
+
+# T_IMPORT -- Convert a generic binary raster file to an IRAF image. The
+# binary file is described either from the task parameters, or as an entry
+# in a database of known formats. Access to the database is either by
+# specifying the format explicitly, or by scanning the database and evaluating
+# an expression which identifies the format. Output is either in the form
+# of information about the file to be converted, a list of the file's pixels
+# or an IRAF image whose bands are computed from a list of expressions.
+
+procedure t_import ()
+
+pointer ip # task structure pointer
+int binfiles # binary files list pointer
+pointer imfiles # output image list pointer
+int fdb # format database descriptor
+int im # image pointer
+pointer sp, bfname, imname # local storage
+pointer format, output, fmt, idstr
+
+int clpopni(), clplen(), imtlen() # function definitions
+int clgfil(), open()
+int locpr(), imtgetim(), fdb_opendb()
+int ip_fcode(), ip_is_builtin()
+pointer imtopenp(), ip_init(), fdb_scan_records(), immap()
+
+extern ip_getop(), ip_dbfcn()
+errchk clpopni, clgfil, imtopenp, open, immap
+
+define done_ 99
+
+begin
+ call smark (sp) # local storage
+ call salloc (bfname, SZ_FNAME, TY_CHAR)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call salloc (format, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (fmt, SZ_FNAME, TY_CHAR)
+ call salloc (idstr, SZ_FNAME, TY_CHAR)
+
+ ip = ip_init () # allocate task struct pointer
+
+ call ieemapr (YES, YES) # enable IEEE NaN mapping
+ call ieemapd (YES, YES)
+
+ # Get file names and image lists.
+ binfiles = clpopni ("binfiles")
+ imfiles = imtopenp ("images")
+
+ # Get the format parameter.
+ call clgstr ("format", Memc[format], SZ_FNAME)
+ call ip_do_fmtpar (ip, Memc[format])
+
+ # Get task output parameters.
+ call ip_gout_pars (ip)
+
+ # See if the image lists match. If the lists are empty and we're
+ # asked for info, just dump the database and leave.
+ if (IP_OUTPUT(ip) != IP_INFO && IP_OUTPUT(ip) != IP_NONE) {
+ if (clplen(binfiles) != imtlen(imfiles) && imtlen(imfiles) != 0) {
+ # Clean up and print an error.
+ call clpcls (binfiles)
+ call imtclose (imfiles)
+ call sfree (sp)
+ call error (1, "Input and output lists not the same length.")
+ }
+ } else if (IP_OUTPUT(ip) == IP_INFO) {
+ if (clplen(binfiles) == 0 && imtlen(imfiles) == 0) {
+ fdb = fdb_opendb ()
+ call ip_list_formats (fdb)
+ call fdb_closedb (fdb)
+ goto done_
+ }
+ }
+
+ while (clgfil (binfiles, Memc[bfname], SZ_FNAME) != EOF) {
+ iferr (IP_FD(ip) = open (Memc[bfname], READ_ONLY, BINARY_FILE)) {
+ call eprintf ("Error opening file '%s'.\n")
+ call pargstr (Memc[bfname])
+ break
+ }
+
+ # Process the outbands parameter.
+ call ip_reset_outbands (ip)
+
+ if (IP_FORMAT(ip) == IP_SENSE) {
+ # Scan the database and get symtab pointer to format record.
+ fdb = fdb_opendb ()
+ call ip_lseek (fdb, BOF)
+ IP_FSYM(ip) = fdb_scan_records (fdb, "image_id",
+ locpr(ip_getop), ip, locpr(ip_dbfcn), ip)
+ if (IP_FSYM(ip) == NULL) {
+ # Try it byte-swapped.
+ IP_SWAP(ip) = S_ALL
+ call ip_lseek (fdb, BOF)
+ IP_FSYM(ip) = fdb_scan_records (fdb, "image_id",
+ locpr(ip_getop), ip, locpr(ip_dbfcn), ip)
+ IP_SWAP(ip) = NULL
+
+ if (IP_FSYM(ip) == NULL) {
+ if (IP_OUTPUT(ip) == IP_INFO) {
+ call printf ("%.19s%20tUnrecognized format\n")
+ call pargstr (Memc[bfname])
+ call fdb_closedb (fdb)
+ next
+ } else {
+ call printf (
+ "Unrecognized format. Known formats include:\n\n")
+ call ip_lseek (fdb, BOF)
+ call ip_list_formats (fdb)
+ call fdb_closedb (fdb)
+ break
+ }
+ }
+ }
+ call fdb_closedb (fdb)
+ }
+
+ # See if this is a 'builtin' format.
+ if (IP_FSYM(ip) != NULL) {
+ call fdbgstr (IP_FSYM(ip), "format", Memc[fmt], SZ_LINE)
+ call fdbgstr (IP_FSYM(ip), "id_string", Memc[idstr], SZ_LINE)
+ call fdb_strip_quote (Memc[idstr], Memc[idstr], SZ_LINE)
+ IP_BLTIN(ip) = ip_is_builtin (Memc[fmt])
+ IP_FCODE(ip) = ip_fcode (Memc[fmt])
+ } else
+ IP_BLTIN(ip) = NO
+
+
+ if (IP_FORMAT(ip) != IP_NONE) {
+ # Evaluate database expressions for this binary file.
+ call ip_eval_dbrec (ip)
+ }
+
+ if (IP_OUTPUT(ip) == IP_INFO) {
+ # Just print some information about the file.
+ call ip_info (ip, Memc[bfname], IP_VERBOSE(ip))
+
+ } else {
+ if (IP_OUTPUT(ip) != IP_NONE) {
+ # Get an output image name.
+ if (IP_OUTPUT(ip) == IP_IMAGE) {
+ if (imtgetim (imfiles, Memc[imname], SZ_FNAME) == EOF)
+ call error (1, "Short image list.")
+ } else if (IP_OUTPUT(ip) == IP_LIST) {
+ # Get a temporary image name.
+ call mktemp ("tmp$imp", Memc[imname], SZ_FNAME)
+ }
+
+ # Open the output image.
+ iferr (im = immap(Memc[imname], NEW_IMAGE, 0)) {
+ call erract (EA_WARN)
+ next
+ }
+ IP_IM(ip) = im
+
+ # Calculate the size of output image and number of bands.
+ IM_LEN(im,1) = IP_AXLEN(ip,1)
+ IM_LEN(im,2) = IP_AXLEN(ip,2)
+ IM_LEN(im,3) = IP_NBANDS(ip)
+ if (IP_NBANDS(ip) > 1)
+ IM_NDIM(im) = 3
+ else
+ IM_NDIM(im) = IP_NDIM(ip)
+ IM_PIXTYPE(im) = IP_OUTTYPE(ip)
+ }
+
+ if (IP_VERBOSE(ip) == YES && IP_OUTPUT(ip) != IP_LIST) {
+ # Print chatter about the conversion.
+ call printf ("%s -> %s\n ")
+ call pargstr (Memc[bfname])
+ call pargstr (Memc[imname])
+ call ip_info (ip, Memc[bfname], NO)
+ call ip_obinfo (ip, Memc[imname])
+ call flush (STDOUT)
+ }
+
+ if (IP_BLTIN(ip) == YES) {
+ call ip_prbuiltin (ip, Memc[bfname])
+ } else {
+ # This is it, process the binary file.
+ if (BAND_INTERLEAVED(ip))
+ # Input file is band interleaved.
+ call ip_prband (ip, IP_FD(ip), IP_IM(ip), NULL)
+ else if (LINE_INTERLEAVED(ip))
+ # Input file is line interleaved.
+ call ip_prline (ip, IP_FD(ip), IP_IM(ip), NULL)
+ else if (PIXEL_INTERLEAVED(ip))
+ # Input file is pixel interleaved.
+ call ip_prpix (ip, IP_FD(ip), IP_IM(ip), NULL)
+ else
+ call error (0, "Unrecognized pixel storage.")
+
+ if (IP_VERBOSE(ip) == YES) {
+ call eprintf (" Status: Done \n")
+ call flush (STDERR)
+ }
+ }
+
+
+ if (IP_IMHEADER(ip) != NULL && IP_OUTPUT(ip) != IP_NONE)
+ # Copy header info to new image (can contain wcs info)
+ call ip_mkheader (IP_IM(ip), Memc[IP_IMHEADER(ip)])
+
+ if (IP_OUTPUT(ip) == IP_LIST) {
+ # List the image pixels band by band.
+ call ip_listpix (IP_IM(ip))
+ call imdelete (Memc[imname])
+ }
+
+ if (IP_IM(ip) != NULL)
+ call imunmap (IP_IM(ip)) # close the output image
+ }
+
+ call close (IP_FD(ip))
+ if (IP_FORMAT(ip) == IP_SENSE)
+ call fdb_close (IP_FSYM(ip)) # free format pointer
+ }
+
+ # Free task structure ptr and clean up.
+ call fdb_close (IP_FSYM(ip))
+done_ call ip_free (ip)
+ call clpcls (binfiles)
+ call imtclose (imfiles)
+ call sfree (sp)
+end
+
+
+# IP_INIT -- Initialize the task structure pointers.
+
+pointer procedure ip_init ()
+
+pointer ptr
+
+begin
+ # Allocate task structure pointer.
+ iferr (call calloc (ptr, SZ_IMPSTRUCT, TY_STRUCT))
+ call error (0, "Error allocating IMPORT task structure.")
+
+ # Allocate the pixtype, outbands, and buffer struct pointers.
+ call calloc (IP_PIXTYPE(ptr), MAX_OPERANDS, TY_POINTER)
+ call calloc (IP_OUTBANDS(ptr), MAX_OPERANDS, TY_POINTER)
+ call calloc (IP_BUFPTR(ptr), MAX_OPERANDS, TY_POINTER)
+
+ # Initialize some parameters
+ IP_IM(ptr) = NULL
+ IP_FD(ptr) = NULL
+ IP_OFFSET(ptr) = 1
+ IP_FLIP(ptr) = FLIP_NONE
+
+ return (ptr)
+end
+
+
+# IP_FREE -- Free the task structure pointers.
+
+procedure ip_free (ip)
+
+pointer ip #i task struct pointer
+
+int i
+
+begin
+ # Free pixtype pointers.
+ for (i=1; i < IP_NPIXT(ip); i=i+1)
+ call mfree (PTYPE(ip,i), TY_STRUCT)
+ call mfree (IP_PIXTYPE(ip), TY_POINTER)
+
+ # Free outbands pointers.
+ for (i=1; i < MAX_OPERANDS; i=i+1)
+ call mfree (OBANDS(ip,i), TY_STRUCT)
+ call mfree (IP_OUTBANDS(ip), TY_POINTER)
+
+ # Free buffer pointers.
+ call mfree (IP_BUFPTR(ip), TY_POINTER)
+
+ if (IP_COMPTR(ip) != NULL)
+ call mfree (IP_COMPTR(ip), TY_CHAR)
+ call mfree (ip, TY_STRUCT)
+end
+
+
+# IP_GIN_PARS -- Get the task input file parameters.
+
+procedure ip_gin_pars (ip)
+
+pointer ip #i task struct pointer
+
+pointer sp, dims, bswap, pixtype
+
+int clgeti()
+
+begin
+ call smark (sp)
+ call salloc (dims, SZ_FNAME, TY_CHAR)
+ call salloc (bswap, SZ_FNAME, TY_CHAR)
+ call salloc (pixtype, SZ_FNAME, TY_CHAR)
+
+ # Get the storage parameters.
+ IP_HSKIP(ip) = clgeti ("hskip")
+ IP_TSKIP(ip) = clgeti ("tskip")
+ IP_BSKIP(ip) = clgeti ("bskip")
+ IP_LSKIP(ip) = clgeti ("lskip")
+ IP_LPAD(ip) = clgeti ("lpad")
+
+ # Process the dims parameter.
+ call aclrc (Memc[dims], SZ_FNAME)
+ call clgstr ("dims", Memc[dims], SZ_FNAME)
+ call ip_do_dims (ip, Memc[dims])
+
+ # Process the bswap parameter.
+ call aclrc (Memc[bswap], SZ_FNAME)
+ call clgstr ("bswap", Memc[bswap], SZ_FNAME)
+ call ip_do_bswap (ip, Memc[bswap])
+
+ # Process the pixtype parameter.
+ call aclrc (Memc[pixtype], SZ_FNAME)
+ call clgstr ("pixtype", Memc[pixtype], SZ_FNAME)
+ call ip_do_pixtype (ip, Memc[pixtype])
+
+ if (IP_NPIXT(ip) > 1)
+ IP_INTERLEAVE(ip) = 0 # composite pixtype, ignore interleave
+ else
+ IP_INTERLEAVE(ip) = clgeti ("interleave")
+
+ # Do a little sanity checking.
+ if (IP_NPIXT(ip) > 1 && IP_NDIM(ip) > IP_NPIXT(ip))
+ call error (1,
+ "Image dimensions don't match `pixtype' specification.")
+ if (IP_NPIXT(ip) == 1 && IP_NDIM(ip) > 2 && (IP_INTERLEAVE(ip) != 0 &&
+ IP_INTERLEAVE(ip) != IP_AXLEN(ip,3)))
+ call error (1,
+ "Dimensions don't match `pixtype' and `interleave' params.")
+
+ if (DEBUG) { call zzi_prstruct ("init inpars", ip) }
+ call sfree (sp)
+end
+
+
+# IP_GOUT_PARS -- Get the task output file parameters.
+
+procedure ip_gout_pars (ip)
+
+pointer ip #i task struct pointer
+
+pointer sp, out, otype, obands, imhead
+int btoi(), clgeti()
+bool clgetb(), streq()
+
+begin
+ call smark (sp)
+ call salloc (out, SZ_FNAME, TY_CHAR)
+ call salloc (otype, SZ_FNAME, TY_CHAR)
+ call salloc (obands, SZ_FNAME, TY_CHAR)
+ call salloc (imhead, SZ_FNAME, TY_CHAR)
+
+ # Get the type of output to do.
+ call aclrc (Memc[out], SZ_FNAME)
+ call clgstr ("output", Memc[out], SZ_FNAME)
+ switch (Memc[out]) {
+ case 'i':
+ if (Memc[out+1] == 'n') # info
+ IP_OUTPUT(ip) = IP_INFO
+ else if (Memc[out+1] == 'm') # image
+ IP_OUTPUT(ip) = IP_IMAGE
+ case 'l': # list
+ IP_OUTPUT(ip) = IP_LIST
+ case 'n': # none, no
+ IP_OUTPUT(ip) = IP_NONE
+ default:
+ call error (2, "Unrecognized output type in 'output'.")
+ }
+
+ # Get the output image type.
+ call aclrc (Memc[otype], SZ_FNAME)
+ call clgstr ("outtype", Memc[otype], SZ_FNAME)
+ switch (Memc[otype]) {
+ case 'u':
+ IP_OUTTYPE(ip) = TY_USHORT
+ case 's':
+ IP_OUTTYPE(ip) = TY_SHORT
+ case 'i':
+ IP_OUTTYPE(ip) = TY_INT
+ case 'l':
+ IP_OUTTYPE(ip) = TY_LONG
+ case 'r':
+ IP_OUTTYPE(ip) = TY_REAL
+ case 'd':
+ IP_OUTTYPE(ip) = TY_DOUBLE
+ default:
+ IP_OUTTYPE(ip) = NULL
+ call error (2, "Unrecognized output image type in 'outtype'.")
+ }
+
+ # Process the outbands parameter.
+ #call ip_reset_outbands (ip)
+
+ # Get optional image header info file name.
+ call aclrc (Memc[imhead], SZ_FNAME)
+ call clgstr ("imheader", Memc[imhead], SZ_FNAME)
+ if (streq (Memc[imhead],"")) {
+ IP_IMHEADER(ip) = NULL
+ } else {
+ call calloc (IP_IMHEADER(ip), SZ_FNAME, TY_CHAR)
+ call strcpy (Memc[imhead], Memc[IP_IMHEADER(ip)], SZ_FNAME)
+ }
+ IP_VERBOSE(ip) = btoi (clgetb("verbose"))
+ IP_SZBUF(ip) = clgeti ("buffer_size")
+
+ if (DEBUG) { call zzi_prstruct ("init outpars", ip) }
+ call sfree (sp)
+end
+
+
+# IP_RESET_OUTBANDS - Initialize the 'outbands' parameter structure to the
+# default values.
+
+procedure ip_reset_outbands (ip)
+
+pointer ip #i task struct pointer
+
+pointer sp, obands
+int i
+
+begin
+ if (IP_OUTPUT(ip) == IP_INFO)
+ return
+
+ call smark (sp)
+ call salloc (obands, SZ_FNAME, TY_CHAR)
+
+ do i = 1, IP_NBANDS(ip)
+ call ip_free_outbands (OBANDS(ip,i))
+
+ # Process the outbands parameter.
+ call aclrc (Memc[obands], SZ_FNAME)
+ call clgstr ("outbands", Memc[obands], SZ_FNAME)
+ call ip_do_outbands (ip, Memc[obands])
+
+ call sfree (sp)
+end
+
+
+# IP_DO_BSWAP -- Read the byte-swap string an load the ip structure.
+
+procedure ip_do_bswap (ip, bswap)
+
+pointer ip #i task struct pointer
+char bswap[ARB] #i byte swap string
+
+char ch, flag[SZ_FNAME]
+int sp, i
+
+int strdic()
+
+begin
+ if (DEBUG) { call eprintf("swap='%s'\n");call pargstr (bswap) }
+
+ sp = 1
+ IP_SWAP(ip) = NULL
+ while (bswap[sp] != EOS) {
+ i = 1
+ for (ch=bswap[sp]; ch != EOS && ch != ','; ch=bswap[sp]) {
+ flag[i] = ch
+ i = i + 1
+ sp = sp + 1
+ }
+ flag[i] = EOS
+ if (DEBUG) { call eprintf("\tflag='%s'\n");call pargstr (flag) }
+
+ switch (strdic (flag, flag, SZ_FNAME, SWAP_STR)) {
+ case 1, 2:
+ IP_SWAP(ip) = or (IP_SWAP(ip), S_NONE)
+ case 3:
+ IP_SWAP(ip) = or (IP_SWAP(ip), S_ALL)
+ case 4:
+ IP_SWAP(ip) = or (IP_SWAP(ip), S_I2)
+ case 5:
+ IP_SWAP(ip) = or (IP_SWAP(ip), S_I4)
+ default:
+ break
+ }
+ }
+end
+
+
+# IP_DO_DIMS -- Parse the 'dims' parameter to get number of axes and dimensions.
+
+procedure ip_do_dims (ip, dims)
+
+pointer ip #i task struct pointer
+char dims[ARB] #i dimension string
+
+char ch
+int sp, ndim, npix
+int ctoi()
+
+begin
+ if (DEBUG) { call eprintf("dims='%s'\n");call pargstr (dims) }
+
+ ndim = 0
+ for (sp=1; ctoi(dims[1],sp,npix) > 0; ) {
+ ndim = ndim + 1
+ IP_AXLEN(ip,ndim) = npix
+ for (ch=dims[sp]; IS_WHITE(ch) || ch == ','; ch=dims[sp])
+ sp = sp + 1
+ }
+ if (ndim == 1)
+ IP_AXLEN(ip,2) = 1
+ IP_NDIM(ip) = ndim
+end
+
+
+# IP_DO_FMTPAR -- Given the format parameter, figure out what to do with it.
+
+procedure ip_do_fmtpar (ip, format)
+
+pointer ip #i task struct pointer
+char format[ARB] #i format string
+
+pointer fsym
+int fd
+
+int fdb_opendb()
+pointer fdb_get_rec()
+bool streq()
+
+begin
+ if (DEBUG) { call eprintf("format='%s'\n");call pargstr(format) }
+
+ IP_FSYM(ip) = NULL
+ if (streq(format,"none")) {
+ # Get the task input parameters.
+ IP_FORMAT(ip) = IP_NONE
+ call ip_gin_pars (ip)
+
+ } else if (streq(format,"sense")) {
+ # Set a flag and figure it out from the database later.
+ IP_FORMAT(ip) = IP_SENSE
+
+ } else {
+ # Get a pointer to a symtab entry for the requested format
+ IP_FORMAT(ip) = IP_NAME
+ fd = fdb_opendb ()
+ fsym = fdb_get_rec (fd, format)
+ call fdb_closedb (fd)
+ if (fsym == NULL) {
+ call error (2,"Requested format not found in the database.")
+ } else
+ IP_FSYM(ip) = fsym
+ }
+end
+
+
+# IP_DO_PIXTYPE -- Process the pixtype parameter
+
+procedure ip_do_pixtype (ip, pixtype)
+
+pointer ip #i task struct pointer
+char pixtype[ARB] #i pixtype string
+
+int i, pp, npix, nbytes
+pointer op
+
+int ctoi()
+
+begin
+ if (DEBUG) { call eprintf("pixtype=:%s:\n");call pargstr(pixtype) }
+
+ # Check for a bonehead user.
+ if (pixtype[2] == EOS || pixtype[2] == ',') {
+ call error (0, "Invalid `pixtype' parameter: no size given")
+ }
+
+ pp = 1
+ npix = 0
+ nbytes = ERR
+ repeat {
+ npix = npix + 1
+
+ call ip_alloc_operand (PTYPE(ip,npix))
+ op = PTYPE(ip,npix)
+
+ # Get pixel type.
+ switch (pixtype[pp]) {
+ case 'b':
+ IO_TYPE(op) = PT_BYTE
+ case 'u':
+ IO_TYPE(op) = PT_UINT
+ case 'i':
+ IO_TYPE(op) = PT_INT
+ case 'r':
+ IO_TYPE(op) = PT_IEEE
+ case 'n':
+ IO_TYPE(op) = PT_NATIVE
+ case 'x':
+ IO_TYPE(op) = PT_SKIP
+ }
+ pp = pp + 1
+
+ # Get the number of bytes.
+ i = ctoi (pixtype, pp, IO_NBYTES(op))
+
+ # Force equivalence of 'b1' and 'u1' pixtypes.
+ if (IO_TYPE(op) == PT_UINT && IO_NBYTES(op) == 1)
+ IO_TYPE(op) = PT_BYTE
+
+ # Get a tag name or create one.
+ if (pixtype[pp] == ',' || pixtype[pp] == EOS) { # no tag given
+ call sprintf (OP_TAG(op), SZ_TAG, "b%d")
+ call pargi (npix)
+ if (pixtype[pp] != EOS)
+ pp = pp + 1
+ } else if (pixtype[pp] == ':') { # get the tag
+ pp = pp + 1
+ for (i=1; (pixtype[pp] != ',' && pixtype[pp] != EOS) ; i=i+1) {
+ Memc[IO_TAG(op)+i-1] = pixtype[pp]
+ pp = pp + 1
+ }
+ pp = pp + 1
+ }
+
+ # Make sure all of the pixtypes are the same datatype.
+ if (nbytes != ERR) {
+ if (nbytes != IO_NBYTES(op))
+ call error (0, "Pixtypes must all be the same size")
+ } else
+ nbytes = IO_NBYTES(op)
+
+ if (DEBUG) { call zzi_prop (op) }
+
+ } until (pixtype[pp] == EOS)
+ IP_NPIXT(ip) = npix
+end
+
+
+# IP_DO_OUTBANDS -- Get the outbands parameter and break it up into a list
+# of individual expressions.
+
+procedure ip_do_outbands (ip, outbands)
+
+pointer ip #i task struct pointer
+char outbands[ARB] #i outbands string
+
+pointer sp, buf
+int i, op, nbands, level
+
+int strsearch()
+
+begin
+ # If there is no outbands parameter specified, warn the user, we'll
+ # make something up later.
+ IP_USE_CMAP(ip) = YES
+ if (outbands[1] == EOS && IP_OUTPUT(ip) != IP_INFO) {
+ call eprintf ("Warning: No 'outbands' parameter specified: ")
+ call eprintf ("Converting all pixels.\n")
+ IP_NBANDS(ip) = ERR
+ return
+ }
+
+ call smark (sp)
+ call salloc (buf, SZ_EXPR, TY_CHAR)
+ call aclrc (Memc[buf], SZ_EXPR)
+
+ if (DEBUG) { call eprintf("outbands='%s'\n");call pargstr(outbands) }
+
+ op = 1
+ nbands = 0
+ while (outbands[op] != EOS) {
+ level = 0
+ nbands = nbands + 1
+ # Copy expr up to the delimiting comma into a buffer.
+ call aclrc (Memc[buf], SZ_EXPR)
+ for (i=0; i < SZ_EXPR; i = i + 1) {
+ if (outbands[op] == '(') {
+ level = level + 1
+ Memc[buf+i] = outbands[op]
+ } else if (outbands[op] == ')') {
+ level = level - 1
+ Memc[buf+i] = outbands[op]
+ } else if ((outbands[op] == ',' && level == 0) ||
+ outbands[op] == EOS) {
+ Memc[buf+i] = EOS
+ op = op + 1
+ break
+ } else if (! IS_WHITE(outbands[op]))
+ Memc[buf+i] = outbands[op]
+ op = op + 1
+ }
+
+ if (Memc[buf] != EOS) {
+ # Save expression to main outbands structure.
+ call ip_alloc_outbands (OBANDS(ip,nbands))
+ call strcpy (Memc[buf], O_EXPR(ip,nbands), SZ_EXPR)
+
+ if (strsearch(Memc[buf], "red") > 0 ||
+ strsearch(Memc[buf], "green") > 0 ||
+ strsearch(Memc[buf], "blue") > 0)
+ IP_USE_CMAP(ip) = NO
+
+ # Load the operand struct.
+ call strcpy (Memc[buf], OP_TAG(O_OP(ip,nbands)), SZ_EXPR)
+
+ if (DEBUG) { call zzi_proband (ip, nbands) }
+ }
+ }
+ IP_NBANDS(ip) = nbands
+ IP_AXLEN(ip,3) = nbands
+
+ call sfree (sp)
+end
+
+
+# IP_ALLOC_OUTBANDS -- Allocate an outbands structure.
+
+procedure ip_alloc_outbands (op)
+
+pointer op #i outbands struct pointer
+
+begin
+ call calloc (op, LEN_OUTBANDS, TY_STRUCT)
+ call calloc (OB_EXPR(op), SZ_EXPR, TY_CHAR)
+ call ip_alloc_operand (OB_OP(op))
+end
+
+
+# IP_FREE_OUTBANDS -- Free an outbands structure.
+
+procedure ip_free_outbands (op)
+
+pointer op #i outbands struct pointer
+
+begin
+ call ip_free_operand (OB_OP(op))
+ call mfree (OB_EXPR(op), TY_CHAR)
+ call mfree (op, TY_STRUCT)
+end
+
+
+# IP_ALLOC_OPERAND -- Allocate an operand structure.
+
+procedure ip_alloc_operand (op)
+
+pointer op #i operand struct pointer
+
+begin
+ call calloc (op, LEN_OPERAND, TY_STRUCT)
+ call calloc (IO_TAG(op), SZ_FNAME, TY_CHAR)
+end
+
+
+# IP_FREE_OPERAND -- Free an operand structure.
+
+procedure ip_free_operand (op)
+
+pointer op #i operand struct pointer
+
+begin
+ call mfree (IO_TAG(op), TY_CHAR)
+ call mfree (op, TY_STRUCT)
+end
diff --git a/pkg/dataio/import/zzidbg.x b/pkg/dataio/import/zzidbg.x
new file mode 100644
index 00000000..25c58778
--- /dev/null
+++ b/pkg/dataio/import/zzidbg.x
@@ -0,0 +1,145 @@
+include <evvexpr.h>
+include "import.h"
+
+procedure zzi_prstruct (whence, ip)
+
+char whence[SZ_FNAME]
+pointer ip
+int i
+
+begin
+ call eprintf ("%s:\n") ; call pargstr (whence)
+ call eprintf ("\tformat=%s interleave=%d bswap=%s\n")
+ switch (IP_FORMAT(ip)) {
+ case IP_NONE: call pargstr ("IP_NONE")
+ case IP_SENSE: call pargstr ("IP_SENSE")
+ case IP_NAME: call pargstr ("IP_NAME")
+ case IP_BUILTIN: call pargstr ("IP_BUILTIN")
+ default: call pargstr ("ERR")
+ }
+ call pargi (IP_INTERLEAVE(ip))
+ switch(IP_SWAP(ip)) {
+ case S_NONE: call pargstr ("S_NONE")
+ case S_ALL: call pargstr ("S_ALL")
+ case S_I2: call pargstr ("S_I2")
+ case S_I4: call pargstr ("S_I4")
+ default: call pargstr ("ERR")
+ }
+ call eprintf ("\thskip=%d tskip=%d bskip=%d lskip=%d lpad=%d\n")
+ call pargi (IP_HSKIP(ip))
+ call pargi (IP_TSKIP(ip))
+ call pargi (IP_BSKIP(ip))
+ call pargi (IP_LSKIP(ip))
+ call pargi (IP_LPAD(ip))
+ call eprintf ("\tndim=%s dims=(%d,%d,%d,%d,%d,%d,%d)\n")
+ call pargi (IP_NDIM(ip))
+ do i = 1, 7
+ call pargi (IP_AXLEN(ip,i))
+
+ call eprintf ("\toutput=%s outtype=%s imheader='%s' verbose=%d\n")
+ switch(IP_OUTPUT(ip)) {
+ case IP_NONE: call pargstr ("IP_NONE")
+ case IP_IMAGE: call pargstr ("IP_IMAGE")
+ case IP_LIST: call pargstr ("IP_LIST")
+ case IP_INFO: call pargstr ("IP_INFO")
+ default: call pargstr ("ERR")
+ }
+ switch(IP_OUTTYPE(ip)) {
+ case TY_SHORT: call pargstr ("TY_SHORT")
+ case TY_INT: call pargstr ("TY_INT")
+ case TY_LONG: call pargstr ("TY_LONG")
+ case TY_REAL: call pargstr ("TY_REAL")
+ case TY_DOUBLE: call pargstr ("TY_DOUBLE")
+ default: call pargstr ("ERR")
+ }
+ if (IP_IMHEADER(ip) == NULL)
+ call pargstr ("")
+ else
+ call pargstr (Memc[IP_IMHEADER(ip)])
+ call pargi (IP_VERBOSE(ip))
+ call eprintf ("\tpixtype:\n")
+ do i = 1, IP_NPIXT(ip) {
+ call eprintf ("\t ")
+ call zzi_prop (PTYPE(ip,i))
+ }
+ call eprintf ("\toutbands:\n")
+ do i = 1, IP_NBANDS(IP) {
+ call eprintf ("\t ")
+ call zzi_proband (ip, i)
+ }
+ call flush (STDERR)
+end
+
+
+procedure zzi_proband (ip,band)
+
+pointer ip
+int band
+
+begin
+ call eprintf ("ob=%d expr='%s' op->")
+ call pargi (OBANDS(ip,band))
+ call pargstr (O_EXPR(ip,band))
+ call zzi_prop (O_OP(ip,band))
+end
+
+
+procedure zzi_prop (o)
+
+pointer o
+char buf[8]
+int type, ip_ptype()
+
+begin
+ call sprintf (buf, 8, " buirnx")
+ type = ip_ptype(IO_TYPE(o), IO_NBYTES(o))
+ call eprintf ("(o=%d expr='%s' tag='%s' (t='%c' N=%d=>%s) Np=%d %d)\n")
+ call pargi (o)
+ call pargstr (Memc[OB_EXPR(o)])
+ call pargstr (OP_TAG(o))
+ call pargc (buf[IO_TYPE(o)+1])
+ call pargi (IO_NBYTES(o))
+ switch (type) {
+ case TY_UBYTE: call pargstr ("TY_UBYTE")
+ case TY_USHORT: call pargstr ("TY_USHORT")
+ case TY_SHORT: call pargstr ("TY_SHORT")
+ case TY_INT: call pargstr ("TY_INT")
+ case TY_LONG: call pargstr ("TY_LONG")
+ case TY_REAL: call pargstr ("TY_REAL")
+ case TY_DOUBLE: call pargstr ("TY_DOUBLE")
+ default: call pargstr ("ERR")
+ }
+ call pargi (IO_NPIX(o))
+ call pargi (IO_DATA(o))
+ call flush (STDERR)
+end
+
+
+procedure zzi_pevop (o)
+
+pointer o
+
+begin
+ call eprintf ("o=%d type=%d len=%d flags=%d ")
+ call pargi (o)
+ call pargi (O_TYPE(o))
+ call pargi (O_LEN(o))
+ call pargi (O_FLAGS(o))
+ switch (O_TYPE(o)) {
+ case TY_CHAR:
+ call eprintf ("val='%s'\n") ; call pargstr (O_VALC(o))
+ case TY_SHORT:
+ call eprintf ("val=%d\n") ; call pargs (O_VALS(o))
+ case TY_INT:
+ call eprintf ("val=%d\n") ; call pargi (O_VALI(o))
+ case TY_LONG:
+ call eprintf ("val=%d\n") ; call pargl (O_VALL(o))
+ case TY_REAL:
+ call eprintf ("val=%g\n") ; call pargr (O_VALR(o))
+ case TY_DOUBLE:
+ call eprintf ("val=%g\n") ; call pargd (O_VALD(o))
+ default:
+ call eprintf ("ptr=%d\n") ; call pargi (O_VALP(o))
+ }
+ call flush (STDERR)
+end