From fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Wed, 8 Jul 2015 20:46:52 -0400 Subject: Initial commit --- pkg/dataio/import/bltins/README | 13 + pkg/dataio/import/bltins/ipcmap.x | 76 ++++ pkg/dataio/import/bltins/ipgif.x | 883 ++++++++++++++++++++++++++++++++++++++ pkg/dataio/import/bltins/ipras.x | 504 ++++++++++++++++++++++ pkg/dataio/import/bltins/ipxwd.x | 188 ++++++++ pkg/dataio/import/bltins/mkpkg | 13 + 6 files changed, 1677 insertions(+) create mode 100644 pkg/dataio/import/bltins/README create mode 100644 pkg/dataio/import/bltins/ipcmap.x create mode 100644 pkg/dataio/import/bltins/ipgif.x create mode 100644 pkg/dataio/import/bltins/ipras.x create mode 100644 pkg/dataio/import/bltins/ipxwd.x create mode 100644 pkg/dataio/import/bltins/mkpkg (limited to 'pkg/dataio/import/bltins') 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 +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 +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 + ipxwd.x ../import.h + ; -- cgit