diff options
author | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
---|---|---|
committer | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
commit | 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch) | |
tree | 4464880c571602d54f6ae114729bf62a89518057 /pkg/dataio/import | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/dataio/import')
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 |