diff options
Diffstat (limited to 'unix/gdev/sgidev')
-rw-r--r-- | unix/gdev/sgidev/README | 24 | ||||
-rw-r--r-- | unix/gdev/sgidev/README.gif | 438 | ||||
-rw-r--r-- | unix/gdev/sgidev/mkpkg | 9 | ||||
-rw-r--r-- | unix/gdev/sgidev/mkpkg.sh | 60 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgi2gif.c | 731 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgi2svg.c | 245 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgi2uapl.c | 545 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgi2ueps.c | 530 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgi2uhpgl.c | 160 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgi2uhplj.c | 223 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgi2uimp.c | 341 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgi2uptx.c | 61 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgi2uqms.c | 296 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgi2xbm.c | 135 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgiUtil.c | 132 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgiUtil.h | 10 | ||||
-rw-r--r-- | unix/gdev/sgidev/sgidispatch.c | 70 |
17 files changed, 4010 insertions, 0 deletions
diff --git a/unix/gdev/sgidev/README b/unix/gdev/sgidev/README new file mode 100644 index 00000000..363b490f --- /dev/null +++ b/unix/gdev/sgidev/README @@ -0,0 +1,24 @@ +SGIDEV -- This directory contains the UNIX dependent sources for the metacode +or bitmap translation programs for all devices supported by the SGI graphics +kernel. See gio$sgikern or `help sgikern' for further information on SGI. + +To add a new SGI device: + + [1] Add source file for translator to this directory. + [2] Add references to mkpkg.csh and mkpkg. + [3] Run `mkpkg update' in this directory to install new translator. + + [4] Add entry to graphcap file, including DD command string + containing host command to dispose of the output. + + [5] Test new device interface. + +Alternatively, you might wish to install the source for the translator in +local somewhere, to avoid a merge operation when a new version of the VMS +host system interface is installed. + +Note that some example graphcap entries for SGI devices might require non- +standard tasks residing outside of IRAF, for example the `impress300' +command to ship Impress output from a UNIX node to a VMS node running +Eunice in order to execute the VMS IMPRINT command. These are considered +so unusual that support is not included in the standard system. diff --git a/unix/gdev/sgidev/README.gif b/unix/gdev/sgidev/README.gif new file mode 100644 index 00000000..85833d3f --- /dev/null +++ b/unix/gdev/sgidev/README.gif @@ -0,0 +1,438 @@ + +Announcement for adass.iraf.system: + + An SGI translator which converts IRAF graphics directly to GIF +images is now available from our anonymous ftp archive as + + ftp://iraf.noao.edu/pub/sgi2gif.c + ftp://iraf.noao.edu/pub/sgi2gif.readme + +The associated readme file describes how to install the translator and +configure a variety of graphcap entries for it. + SGI translators are used to convert IRAF graphics to some other +format, usually Postscript, for disposal to a printer or some other +hardcopy device. The SGI2GIF translator now allows users to generate +GIF images (suitable for web page presentation) directly from IRAF using +the familiar ":.snap" command or non-interactively. See the readme file +for a full discussion of the capabilities and configuration options, or +contact site support (iraf@noao.edu) with questions or problems. + +-------------------------------------------------------------------------------- + +README: + +1. Introduction +--------------- + + IRAF hardcopy graphics are generated by converting the graphics +metacode through the SGI (Simple Graphics Interface) kernel which +translates the numerous graphics commands to a minimal set of move/draw +instructions or a bitmap raster of the plot. In the case of +hardcopy/output graphics (i.e. the SGI kernel), the dev$graphcap file +defines parameters for this conversion which include the plot size, SGI +kernel options, and most especially a "device dispose" (DD) string which +specifies the SGI translator to be used and what to do with the resulting +translator output. The SGI kernel is not a full graphics kernel so +information such as line color and fill areas are lost, below we will +discuss how to retain this when producing a GIF images using other +translators and graphcap file trickery. + + For most printer devices the "sgi2uapl" Postscript translator is +used to convert the SGI kernel metacode from a series of move/draw +instructions to equivalent postscript commands, other translators are +available to convert to other printer languages. The SGI kernel can also +be used, with the proper graphcap entries, to generate a bitmap raster of +the plot which can be easily converted to various image formats. The SGI2GIF +translator takes advantage of this latter feature to produce GIF images +directly from the IRAF graphics metacode. + + The translator has options for specifying the image size, +foreground and background colors, GIF transparency, and can be used to +convert multiple input bitmap files or a single file containing multiple +graphics frames. It allows users to easily generate images suitable for +presentation on the web, either manually or automatically. + + +2. Installation +--------------- + + The SGI translator is distributed in source form and to be used +must be compiled and installed in the system hbin$ directory. To install +the new SGI translator follow these steps while logged in through the iraf +user account: + + [1] Download the translator from the IRAF anonymous FTP archive or + one of it's mirror sites using: + + % ftp iraf.noao.edu (140.252.1.1) + login: anonymous + password: [your email address] + ftp> cd /pub + ftp> mget sgi2gif.c + ftp> quit + + [2] Compile the source using + + % cc -o sgi2gif.e sgi2gif.c # compile the source + % mv sgi2gif.e $hbin # move to the $hbin + + "$hbin" is defined in the iraf environment to be something like + $iraf/unix/bin.<arch>, where <arch> would be 'ssol' for Solaris, + 'sparc' for SunOS and so on. + + [3] Optionally place the source in the directory $iraf/unix/gdev/sgidev. + + [4] Edit the dev$graphcap file and add the following default entries + for the device near the top of the file: + + g-gif|UNIX generic interface to multi-frame GIF file generator:\ + :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \ + -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; \ + rm $F.[1-8]; }&:MF#8:NF:tc=sgi_image_format: + + sgi_image_format|Generic raster file format specification:\ + :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\ + :xr#640:yr#480 :PX#640:PY#480 :XW#640:YW#480:\ + :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0: + + The 'g-gif' entry takes one or more graphics file input and converts + each input frame to a redirected file on output called 'sgigifXXX.gif' + where the 'XXX' is frame number. See below for details one + configuring other graphcap entries. + + +2. Translator Options +--------------------- + The SGI2GIF translator allows the following options: + + -w N Set the width of input bitmap and output image. The + argument must be derived from the graphcap value since + that is what the SGI kernel will use when generating the + bitmap, e.g. "-w $(PX)" instead of "-w 640". + + -h N Set the height of input bitmap and output image. The + argument must be derived from the graphcap value since + that is what the SGI kernel will use when generating the + bitmap, e.g. "-h $(PY)" instead of "-h 640". + + -i Invert the bitmap before conversion. By default the + graphics are drawn using the foreground color, this + option inverts the bitmap before conversion meaning the + graphics are drawn using the background color. + + -t Set background color as transparent. If enabled the + translator will produce a GIF89 format image with the + background color set as "transparent". When this image + is used with an HTML document the background color is + the HTML page color. + + -root Set the root rame for output file. If defined this + root name will be combined with the frame number and + a ".gif" extension to form the output name. If not + defined and only one input image is present the default + action is to send the output to STDOUT. + + -fg R G B Specify foreground color (default 'black'). Set the + foreground color as a triplet of RGB values in the + range 0-255. The -fg flag must have three arguments. + + -bg R G B Specify background color (default 'white'). Set the + foreground color as a triplet of RGB values in the + range 0-255. The -bg flag must have three arguments. + + +3. Configuring Alternate Graphcap Entries +----------------------------------------- + + Most of the work in a graphcap entry is done by the 'device +dispose' (i.e. "DD") string. This string is composed of three comma +delimited parts: a node/device name (which is normally ignored), a +temporary filename, and a host dispose command. To configure a new entry +it is only this last field that normally needs to be modified, perhaps in +conjunction with another graphcap parameter. As an example let's look at +the DD string used in the example graphcap above: + + :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \ + -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; rm $F.[1-8]; }&: + +where 'ugif' is the unused node/device name, 'tmp$sgk' is the temporary +filename, and the remainder is a host dispose command. The 'sgidispatch' +command is an iraf binary that launches the specified translator +('sgi2gif' here) with any required arguments. Note that everything within +the "!{...}&" curly braces is executed (as a background Bourne shell +command) so any string of valid unix command separate by a semicolon will +be executed. In this case the sgidispatch command launches the sgi2gif +translator with all of it's arguments, it then deletes the input metacode +file symbolized by the "$F". + You may notice that some arguments are specified as e.g. "-w +$(PX)". When the DD string is executed any macro values beginning with a +'$' such as '$(PX)' are replaced with values from the rest of the graphcap +entry. In this case '$(PX)' is replaced by the value contained in the +graphcap :PX (physical X size) field, the "$F.[1-8]" is expanded to +include the unique root filename along with any extension 1 thru 8 which may +be generated because of multiple plots in the input. In +most cases all you may need to change in the DD string itself is the +output file, or e.g. whether it gets piped to some other command. + + +3.1 Changing Image Size +----------------------- + + Changing the image size is simply a matter of changing the graphcap +parameters + + :xr#640:yr#480: sets X,Y device resolution + :PX#640:PY#480: sets X,Y physical size of bitmap + :XW#640:YW#480: sets X,Y width of plotting window + +These are defined in the 'sgi_image_format' entry given above. Graphics +are drawn using Normalized Device Coordinates ('NDC', values in the range +0.0 to 1.0) and will be scaled appropriately for any specified output +dimensions allowing users to configure graphcap entries for images which are +larger/smaller than the default, or have square or elongated aspect ratios. + +3.2 Preserving Color Information +-------------------------------- + + Colors such as those used for the axis labels and frame, and colors +used in the plot itself for different line/marker types cannot be preserved +by the SGI kernel directly. To do this you must use a full graphics kernel +such as the PSIKERN postscript kernel found in STSDAS. The V2.11 +distribution contains graphcap entries suitable for this kernel but assumes +you have STSDAS available. See the online help for more information about +this kernel. + Using the '-fg' and '-bg' flags will allow you to specify foreground +and background colors to be used for the plot as a whole. Note that these +flags require three arguments to specify the RGB color components. The '-t' +flag may be used to mark the background color as 'transparent' so only the +foreground color is shown when the image is used in an HTML document. + +3.3 Generating Other Image Formats +---------------------------------- + + GIF may be used as an intermediate format which can be converted to +something else as part of the graphcap DD string. For example, to use the +ImageMagick CONVERT task to produce a JPEG image the graphcap DD string +could be written as + + g-jpeg|UNIX generic interface to JPEG file generator:\ + :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \ + -bg 0 0 0 -fg 255 255 255 -root sgi $F | \ + convert sgi$$.gif sgi$$.jpg ; rm $F; }&: \ + :MF#1:NF:tc=sgi_image_format: + +The DD string first uses the SGI2GIF translator to produce a 'sgi.gif' +image, then calls the convert task (which is assumed to be in the user's +path) to convert this to JPEG as a separate step. The :MF field is +set to one meaning each frame will generate a new file. The '$$' used in +the filenames (e.g. 'sgi$$.gif') is the process id created for the shell +running the DD command meaning multiple filenames of the form 'sgi12345.gif' +will be created, each with a unique id number so the images aren't over- +written. In the past this form of DD string could be used with the standard +sgi2uapl postscript translator and a host task such as 'gs' to convert +postscript to some other format. + +4. Interfacing to Web CGI Scripts +---------------------------------- + + It would be impossible to give complete details about interfacing +IRAF programs to CGI scripts due to the variety of languages and tasks +that may be used. To begin lets look at how to execute a task from the +host level, which is essentially what we'll be doing from within a CGI +script. + In principle this can be done in one of two ways: Either invoke +the executable directly with the correct command line arguments, or run +the CL with the input redirected to execute the task. In the first case +you must know in which executable the task resides, core IRAF system tasks +(e.g. things in the PLOT and IMAGES packages) have their executables in +the main $iraf/bin.<arch> directory, NOAO package tasks have the +executables in the $iraf/noao/bin.<arch> directory. There is usually a +separate executable for each package and you can probably figure out which +one goes for each package otherwise just look at the package cl file to +find out, for example the PLOT package defines the task in the +$iraf/pkg/plot/plot.cl file, if you look in their you'll see that is +defines the tasks as (part of the file reads) + +task contour, + surface, hafton, velvect = "plot$x_ncar.e" + +which means that the CONTOUR, SURFACE, etc tasks are in the "x_ncar.e" +executable. + Once you find the correct binary, you need to create a file with +the task parameters: usually it's easiest to set the parameters and then +dump the parameter file with 'dpar', e.g. + + cl> dpar listpix > listpix.par + +It's likely that CGI scripts will need to set certain parameters itself so +thought must be given to how to edit this list of default parameters with +values given in the CGI script. + +To run the task you would then do something like: + + % $iraf/bin.sparc/x_images.e listpix @listpix.par + +In this case you must be careful that ALL of the task parameters are +defined, this is done by 'dpar' but empty string parameters will always +be prompted for. On a host command line simply respond to the parameter +prompts by hitting the return key, from with a CGI script these must +be supplied automatically in some way (e.g. via redirection). + In the second case you create a command file and input it to the +cl, for example + + % cl < cl.input >& some_logfile + +where cl.input contains CL commands such as + + wfits.scale=no # set a parameter wfits image*.imh + mta # call a task + logout # logout of the CL + +You must be careful about making sure you are in the right directory and +that parameters are given explicitly if they're like to change, but with +this approach you can call any iraf task. + +4.1 Graphics Tasks +------------------- + + Regardless of the method chosen, you need to be careful about +redirecting any required input or text/graphics output. Graphics output +can be redirected either by setting the "device" parameter to e.g. 'vdm' +to create a file called 'vdm' in the uparm directory, or using the '>G' CL +syntax as in + + cl> surface dev$pix >G surf.plot # redirect metacode to a file + cl> surface dev$pix dev="vdm" # save metacode to uparm dir + cl> surface dev$pix dev="stdplot" # to print it out + cl> gflush # flush graphics buffer + +Which of these approaches works best for depends depends on the tasks you +need and the method of execution chosen above. Note that the ">G" syntax +will only work for tasks executed within the CL, setting a device +parameter to something that creates a file will work with either method. + For non-interactive tasks like SURFACE or CONTOUR this file is +created automatically, interactive tasks however may need to create +metacode files explicitly or else the CGI script must take care to extract +only those plots of interest from the metacode file (e.g. with a separate +call to GKIEXTRACT). + Interactive tasks must also satisfy requests for cursor commands, +including the usual 'q' keystroke needed to exit the task. Since cursor +commands are in reality queries to the CL any binary run as a host task +will generate a cursor prompt on the standard output the same as for any +other parameter query. The response to a cursor query however is usually +of the form + x y wcs key strval + +where 'x' and 'y' are the cursor position, 'wcs' is the WCS of those coords +(usually not important), 'key' is the keystroke you would normally enter, +and if 'key' is a color the 'strval' is the remainder of that color command. +See section 3.7 of the "help cursors" help page for more details on alternate +graphics input. Note however, that your CGI script must know in advance the +order in which the prompts will occur to be able to satisfy them correctly, +e.g. any parameter prompts generated by empty string values should be met +with a newline, and cursor prompts with something as above. Since the tasks +will be very narrowly defined as to how they are run this usually isn't +difficult to set up. + +4.2 Example +----------- + + As an example let create a CGI script to execute the PCOL task +from a web interface. All that we need to do this is the PLOT package +binary to execute the task, a 'graphcap' file, and the SGIKERN binary in +order to convert our graphics metacode to a GIF format using the specified +graphcap entries and the newly installed SGI2GIF translator. In the +following we detail the steps involved in creating this script on a system +with IRAF installed, your application may vary somewhat. We use a +C-shell script here but the same principles apply to all scripting +languages, users should contact site support with questions. + +----------------------------------------------------------------------------- + +#!/bin/csh -f +# +# Sample CGI script demonstrating the using the PCOL graphics task to +# produce an 'sgigif.gif' file of the resulting plot which can be shown +# as an image of the output web page. The script does not show how to +# parse arguments or format the resulting HTML page. All that is required +# for IRAF execution is the binary for the task to be run, the SGIKERN +# binary, and a graphcap file to produce the GIF (given below). The CGI +# script can define the task parameters itself or use a predefined 'dpar' +# dump to set defaults as we do below. + +# The REMOTE_ADDR variable is defined in the environment of the CGI +# script automatically, we specify it here for demonstration purposes. +set REMOTE_ADDR = 140.252.30.95 + +# This would be defined as the graphcap file installed for the local web +# server. + +# The only graphcap entries needed to output graphics to a GIF file using +# the SGI translator is as follows: +# +# vdm|stdvdm|Virtual Device Metafile:\ +# :co#80:li#35:xr#1024:yr#1024:zr#256:ar#.77:ch#.0294:cw#.0125:\ +# :X1#0:X2#1023:Y1#0:Y2#1023: +# +# g-gif|UNIX generic interface to multi-frame GIF file generator:\ +# :DD=ugif,tmp$sgk,!{ /<path>/sgi2gif.e -w $(PX) -h $(PY) \ +# -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; \ +# rm $F.[1-8]; }&:MF#8:NF:tc=sgi_image_format: +# +# sgi_image_format|Generic raster file format specification:\ +# :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\ +# :xr#640:yr#480:PX#640:PY#480:XW#640:YW#480:\ +# :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0: +# +# Note that the path to the sgigif.e binary is specified explicitly, this +# must be replaced by the path to the actual binary. +# +# On the web server this file would normally be installed in the cgi-bin +# or some other directory, the cgi script itself needs to define this location +# with the following variable: + +set graphcap = /tmp/graphcap + +# A uparm directory needs to be defined for saving the VDM file. This is +# defined based on the REMOTE_ADDR so we can have multiple connections +# running at the same time without concurrency problems. + +set uparm = /tmp/uparm-$REMOTE_ADDR/ + +# Create the uparm directory we'll be using... +mkdir $uparm + +# Execute the graphics task desired. In this example we're running the PCOL +# task and assume we've saved the parameters to a 'pcol.dpar' file in the +# current directory. In practice the parameters can be specified using a +# dpar file in the cgi-bin dir or explicitly on the command line. To execute +# the task we call the binary directly, direct output to /dev/null and +# redirect input blank lines to respond to params that take no value. We +# must set the uparm and graphcap values set above to handle the graphics. +# The CGI script can insert values such as 'image' based on arguments, the +# defaults come from a predefined dpar file. + +/iraf/iraf/bin.ssun/x_plot.e >>& /dev/null << EOF +set uparm = $uparm +set graphcap = $graphcap +pcol @pcol.dpar pcol.device="vdm" + +EOF + +# At this point the GKI metacode is saved in the uparm$vdm file, where +# 'uparm' is set above and is created by the custom graphcap file we're +# using. To convert GKI metacode to the final GIF file we call the SGIKERN +# directly and specify the device as 'g-gif' which produces an 'sgigif.gif' +# file in the current directory. Graphcap entries can be created to name +# the file anything desired, that filename is then used as a URL for the +# web page returned. + +/iraf/iraf/bin.ssun/x_sgikern.e >>& /dev/null << EOF +set uparm = $uparm +set graphcap = $graphcap +sgikern input=uparm\$vdm device=g-gif generic=yes +EOF + +# Finally, clean up the temp files we've created. +/bin/rm -rf $uparm + diff --git a/unix/gdev/sgidev/mkpkg b/unix/gdev/sgidev/mkpkg new file mode 100644 index 00000000..e9dac3df --- /dev/null +++ b/unix/gdev/sgidev/mkpkg @@ -0,0 +1,9 @@ +# Make the SGI device host level translation programs [MACHDEP]. + +$call update +$exit + +update: + ! sh -x mkpkg.sh + ! mv $hlib/sgi*.e $hbin + ; diff --git a/unix/gdev/sgidev/mkpkg.sh b/unix/gdev/sgidev/mkpkg.sh new file mode 100644 index 00000000..85d6c83a --- /dev/null +++ b/unix/gdev/sgidev/mkpkg.sh @@ -0,0 +1,60 @@ +# Make the SGI translators and install them in hlib. + +$CC -c $HSI_CF sgiUtil.c + +$CC -c $HSI_CF sgidispatch.c +$CC $HSI_LF sgidispatch.o ../../hlib/libos.a $HSI_LIBS -o sgidispatch.e +mv -f sgidispatch.e ../../hlib +rm sgidispatch.o + +$CC -c $HSI_CF sgi2uimp.c +$CC $HSI_LF sgi2uimp.o sgiUtil.o $HSI_LIBS -o sgi2uimp.e +mv -f sgi2uimp.e ../../hlib +rm sgi2uimp.o + +$CC -c $HSI_CF sgi2uapl.c +$CC $HSI_LF sgi2uapl.o sgiUtil.o $HSI_LIBS -o sgi2uapl.e +mv -f sgi2uapl.e ../../hlib +rm sgi2uapl.o + +$CC -c $HSI_CF sgi2uqms.c +$CC $HSI_LF sgi2uqms.o sgiUtil.o $HSI_LIBS -o sgi2uqms.e +mv -f sgi2uqms.e ../../hlib +rm sgi2uqms.o + +$CC -c $HSI_CF sgi2uptx.c +$CC $HSI_LF sgi2uptx.o sgiUtil.o $HSI_LIBS -o sgi2uptx.e +mv -f sgi2uptx.e ../../hlib +rm sgi2uptx.o + +$CC -c $HSI_CF sgi2uhplj.c +$CC $HSI_LF sgi2uhplj.o sgiUtil.o $HSI_LIBS -o sgi2uhplj.e +mv -f sgi2uhplj.e ../../hlib +rm sgi2uhplj.o + +$CC -c $HSI_CF sgi2uhpgl.c +$CC $HSI_LF sgi2uhpgl.o sgiUtil.o $HSI_LIBS -o sgi2uhpgl.e +mv -f sgi2uhpgl.e ../../hlib +rm sgi2uhpgl.o + +$CC -c $HSI_CF sgi2ueps.c +$CC $HSI_LF sgi2ueps.o sgiUtil.o $HSI_LIBS -o sgi2ueps.e +mv -f sgi2ueps.e ../../hlib +rm sgi2ueps.o + +$CC -c $HSI_CF sgi2gif.c +$CC $HSI_LF sgi2gif.o sgiUtil.o $HSI_LIBS -o sgi2gif.e +mv -f sgi2gif.e ../../hlib +rm sgi2gif.o + +$CC -c $HSI_CF sgi2xbm.c +$CC $HSI_LF sgi2xbm.o sgiUtil.o $HSI_LIBS -o sgi2xbm.e +mv -f sgi2xbm.e ../../hlib +rm sgi2xbm.o + +$CC -c $HSI_CF sgi2svg.c +$CC $HSI_LF sgi2svg.o sgiUtil.o $HSI_LIBS -o sgi2svg.e +mv -f sgi2svg.e ../../hlib +rm sgi2svg.o + +rm sgiUtil.o diff --git a/unix/gdev/sgidev/sgi2gif.c b/unix/gdev/sgidev/sgi2gif.c new file mode 100644 index 00000000..e46d4d28 --- /dev/null +++ b/unix/gdev/sgidev/sgi2gif.c @@ -0,0 +1,731 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include "sgiUtil.h" + + +/* + * SGI2GIF.C -- Read an IRAF SGI bitmap file on standard input and convert + * to a GIF format image on standard outout. + * + * Usage: + * sgi2gif.e [-params] [ [sgi_bitmap] [sgi_bitmap] ... ] + * + * -w N width of input bitmap and output image + * -h N height of input bitmap and output image + * -i invert the bitmap values before conversion + * -t set background color as transparent + * -root set the root rame for output file (default stdout) + * -fg R G B specify foreground color + * -bg R G B specify background color + * + * The input file name and the switches may occur in any order. The + * foreground/background flags require three arguments giving the values + * of the RGB components of the color as a decimal number in the range 0-255. + * Enabling the transparency flag will cause a GIF 89 image to be written, + * otherwise the default will be a GIF 87 format image. The transparent + * color will always be the backgrund color. The bitmap may be inverted + * here using the -i flag. + * + * Sample graphcaps for this translator might look like: + * + * g-gif|UNIX generic interface to multi-frame GIF file generator:\ + * :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \ + * -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; \ + * rm $F.[1-8]; }&:MF#8:NF:tc=sgi_image_format: + * + * sgi_image_format|Generic raster file format specification:\ + * :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\ + * :xr#640:yr#480:PX#640:PY#480:XW#640:YW#480:\ + * :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0: + * + * The 'g-gif' entry takes one or more graphics file input and converts + * each input frame to a redirected file on output called 'sgigifXXX.gif' + * where the 'XXX' is frame number. + * + * To change the image size the graphcap :xr, :PX, :XW (X-dimension) and + * :yr, :PY, :XY (Y-dimension) fields all need to be changed. The -i + * or -t flags must be specified in the graphcap DD string along with the + * -fg/bg flags and their arguments. + */ + + +#define NBITS_CHAR 8 /* number of bits in a char */ +#define DEF_WIDTH 640 /* default image width */ +#define DEF_HEIGHT 480 /* default image height */ +#define DEF_BG 255 /* default background RGB */ +#define DEF_FG 0 /* default foreground RGB */ +#define MAX_INFILES 16 /* max number of input bitmaps */ +#define SZ_FNAME 64 /* size of a filename */ + +typedef int code_int; +typedef long int count_int; +typedef unsigned char byte; + +static byte *pixels; + +static int px = DEF_WIDTH; +static int py = DEF_HEIGHT; +static int nrows = DEF_HEIGHT; +static int ncols = DEF_WIDTH; +static int transparent = 0; +static int invert = 0; +static int red[] = { DEF_BG, DEF_FG } ; +static int green[] = { DEF_BG, DEF_FG } ; +static int blue[] = { DEF_BG, DEF_FG } ; +static char *infile[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static char *s_root = "sgigif_"; + +static int GIFNextPixel(); +static void BumpPixel(), GIFEncode(), Putword(), compress(); +static void output(), cl_block(), cl_hash(), char_init(); +static void char_out(), flush_char(), unpack1to8(); + + + +/* MAIN -- Main entry point for the task. + */ +int +main (int argc, char *argv[]) +{ + FILE *fdi, *fdo; + char fname[SZ_FNAME]; + char *root = s_root; + byte *buffer, *ip; + int i, index, numin=0, len_buf; + int interlace, background, bpp; + + + /* Process the command line. + */ + for (i=1; i < argc; i++) { + if (argv[i][0] == '-') { + if (strcmp (argv[i], "-w") == 0) { + ncols = px = atoi (argv[++i]); + } else if (strcmp (argv[i], "-h") == 0) { + nrows = py = atoi (argv[++i]); + } else if (strcmp (argv[i], "-i") == 0) { + invert++; + } else if (strcmp (argv[i], "-root") == 0) { + root = argv[++i]; + } else if (strcmp (argv[i], "-t") == 0) { + transparent++; + } else if (strcmp (argv[i], "-bg") == 0) { + if (isdigit(argv[++i][0])) + red[0] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + if (isdigit(argv[++i][0])) + green[0] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + if (isdigit(argv[++i][0])) + blue[0] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + } else if (strcmp (argv[i], "-fg") == 0) { + if (isdigit(argv[++i][0])) + red[1] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + if (isdigit(argv[++i][0])) + green[1] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + if (isdigit(argv[++i][0])) + blue[1] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + } else { + fprintf (stderr, "sgi2gif: unknown switch '%s'\n", argv[i]); + } + } else { + /* input sgi-bitmap file specification */ + if (numin < MAX_INFILES) + infile[numin++] = argv[i]; + } + } + + /* Allocate space for the images. */ + len_buf = px / NBITS_CHAR; + buffer = (byte *) malloc (len_buf); + ip = pixels = (byte *) malloc (px * (py + 1)); + + /* Loop over the input bitmaps, writing the converted output to + * either stdout or a filename. + */ + for (index = 0; index == 0 || index < numin; index++) { + + /* Open the input file. */ + fdi = (infile[index] ? fopen (infile[index], "r") : stdin); + + /* Open the output file. For multiple input files force each + * output to a new image, when reading from stdin or only one + * bitmap write to stdout if we didn't set the rootname. + */ + if (numin <= 1 && strcmp (root, s_root) == 0) { + fdo = stdout; + } else { + if (numin > 1) + sprintf (fname, "%s%d.gif", root, index); + else + sprintf (fname, "%s.gif", root); + fdo = fopen (fname, "w+"); + } + + /* Now unpack this bitmap to the output image as byte data. */ + ip = pixels; + while (fread (buffer, len_buf, 1, fdi)) { + /* If we're on a MSB ordered machine wordswap the bitmap so + * it's in the correct order for unpacking to be interpreted + * as an LSB-ordered image. + */ + if ( ! isSwapped ()) + bswap4 (buffer, buffer, len_buf); + + unpack1to8 ((ip+=px), buffer, px); + } + + /* All set, write it out. */ + GIFEncode (fdo, px, py, (interlace=0), (background=0), (bpp=1), + red, green, blue); + + fflush (fdi); + fflush (fdo); + if (fdi != stdin) + fclose (fdi); + if (fdo != stdout) + fclose (fdo); + } + + /* Clean up. */ + free (buffer); + free (pixels); + + return (0); +} + + +/* UNPACK1TO8 -- Unpack each bit in the bitmap to a byte on output. + */ + +static void +unpack1to8 (byte *dest, byte *src, int len) +{ + register int i, b; + byte c = 0; + + for (i = 0, b = 0; i < len; i++) { + if (b > 7) { + b = 0; + c = (invert ? ~(*src++) : (*src++) ); + } + *dest++ = (byte) ((c >> (b++)) & 1); + } +} + + +/* GIF Writing Procedures. + * + * Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A + * Lempel-Zim compression based on "compress". Original Copyright 1990, + * David Koblas, heavily modified since then.... + */ + +#define GIFBITS 12 + +static int Width, Height; +static int curx, cury; +static long CountDown; +static int Interlace; + + +/* GIFENCODE -- GIF Image compression interface. + */ + +static void +GIFEncode (fp, GWidth, GHeight, GInterlace, Background, Bpp, Red, Green, Blue) +FILE *fp; +int GWidth, GHeight; +int GInterlace; +int Background; +int Bpp; +int Red[], Green[], Blue[]; +{ + int B; + int RWidth, RHeight; + int LeftOfs, TopOfs; + int Resolution; + int ColorMapSize; + int InitCodeSize; + int i; + + Interlace = GInterlace; + + ColorMapSize = 1 << Bpp; + + RWidth = Width = GWidth; + RHeight = Height = GHeight; + LeftOfs = TopOfs = 0; + + Resolution = Bpp; + + /* Calculate number of bits we are expecting */ + CountDown = (long)Width * (long)Height; + + /* The initial code size */ + if (Bpp <= 1) + InitCodeSize = 2; + else + InitCodeSize = Bpp; + + /* Set up the current x and y position */ + curx = cury = 0; + + /* Write the Magic header */ + fwrite ((transparent ? "GIF89a" : "GIF87a"), 1, 6, fp); + + /* Write out the screen width and height */ + Putword (RWidth, fp); + Putword (RHeight, fp); + + /* Indicate that there is a global colour map */ + B = 0x80; /* Yes, there is a color map */ + + /* OR in the resolution */ + B |= (Resolution - 1) << 5; + + /* OR in the Bits per Pixel */ + B |= (Bpp - 1); + + /* Write it out */ + fputc (B, fp); + + /* Write out the Background colour */ + fputc (Background, fp); + + /* Byte of 0's (future expansion) */ + fputc (0, fp); + + /* Write out the Global Colour Map */ + for (i = 0; i < ColorMapSize; ++i) { + fputc (Red[i], fp); + fputc (Green[i], fp); + fputc (Blue[i], fp); + } + + /* If doing transparency, write the extension. */ + if (transparent) { + fputc (0x21, fp); /* graphics extension... */ + fputc (0xf9, fp); /* transparency... */ + fputc (0x4, fp); + fputc (0x1, fp); + fputc (0x0, fp); + fputc (0x0, fp); + fputc ((char) 0, fp); /* background color index */ + fputc (0x0, fp); + } + + /* Write an Image separator */ + fputc (',', fp); + + /* Write the Image header */ + Putword (LeftOfs, fp); + Putword (TopOfs, fp); + Putword (Width, fp); + Putword (Height, fp); + + /* Write out whether or not the image is interlaced */ + if (Interlace) + fputc (0x40, fp); + else + fputc (0x00, fp); + + /* Write out the initial code size */ + fputc (InitCodeSize, fp); + + /* Go and actually compress the data */ + compress (InitCodeSize + 1, fp); + + /* Write out a Zero-length packet (to end the series) */ + fputc (0, fp); + + /* Write the GIF file terminator */ + fputc (';', fp); +} + + +/* Bump the 'curx' and 'cury' to point to the next pixel + */ +static void +BumpPixel() +{ + /* Bump the current X position */ + ++curx; + + /* If at the end of a scan line, set curx back to the beginning. */ + if (curx == Width) { + curx = 0; + ++cury; + } +} + + +/* Return the next pixel from the image + */ +static int +GIFNextPixel () +{ + int r; + + if (CountDown == 0) + return EOF; + + --CountDown; + r = (int) pixels[ cury * ncols + curx ] ; + BumpPixel(); + return r; +} + + +/* Write out a word to the GIF file + */ +static void +Putword (w, fp) +int w; +FILE*fp; +{ + unsigned short val = w; + + fputc (val & 0xff, fp); + fputc ((val / 256) & 0xff, fp); +} + + +/* + * GIF Image compression - modified 'compress' + * + * Based on: compress.c - File compression ala IEEE Computer, June 1984. + * + * By Authors: Spencer W. Thomas, Jim McKie, Steve Davies, Ken Turkowski, + * James A. Woods, Joe Orost + * + * Lempel-Ziv compression based on 'compress'. GIF modifications by + * David Rowley (mgardi@watdcsu.waterloo.edu) + */ + +#define HSIZE 5003 /* 80% occupancy */ + +static int n_bits; /* number of bits/code */ +static int maxbits = GIFBITS; /* user settable max # bits/code */ +static code_int maxcode; /* maximum code, given n_bits */ + /* should NEVER generate this code */ +static code_int maxmaxcode = (code_int) 1 << GIFBITS; +#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) + +static count_int htab[HSIZE]; +static unsigned short codetab [HSIZE]; +#define HashTabOf(i) htab[i] +#define CodeTabOf(i) codetab[i] + +/* To save much memory, we overlay the table used by compress() with those + * used by decompress(). The tab_prefix table is the same size and type + * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We + * get this from the beginning of htab. The output stack uses the rest + * of htab, and contains characters. There is plenty of room for any + * possible stack (stack used to be 8000 characters). + */ + +#define tab_prefixof(i) CodeTabOf(i) +#define tab_suffixof(i) ((unsigned char *)(htab))[i] + +static code_int free_ent = 0; /* first unused entry */ +static code_int hsize = HSIZE; /* for dynamic table sizing */ + + +/* block compression parameters -- after all codes are used up, + * and compression rate changes, start over. + */ +static int clear_flg = 0; + +/* + * compress stdin to stdout + * + * Algorithm: use open addressing double hashing (no chaining) on the + * prefix code / next character combination. We do a variant of Knuth's + * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime + * secondary probe. Here, the modular division first probe is gives way + * to a faster exclusive-or manipulation. Also do block compression with + * an adaptive reset, whereby the code table is cleared when the compression + * ratio decreases, but after the table fills. The variable-length output + * codes are re-sized at this point, and a special CLEAR code is generated + * for the decompressor. Late addition: construct the table according to + * file size for noticeable speed improvement on small files. Please direct + * questions about this implementation to ames!jaw. + */ + +static FILE *g_outfile; +static int g_init_bits; +static int ClearCode; +static int EOFCode; +static int cur_bits = 0; + +static unsigned long cur_accum = 0; +static unsigned long masks[] = { + 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, + 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, + 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +static int a_count; /* Number of characters so far in this 'packet' */ +static char accum[256]; /* Define the storage for the packet accumulator */ + +static void +compress (init_bits, outfile) +int init_bits; +FILE *outfile; +{ + register long fcode; + register code_int i /* = 0 */; + register int c; + register code_int ent; + register code_int disp; + register code_int hsize_reg; + register int hshift; + + /* Set up the globals: g_init_bits - initial number of bits + * g_outfile - pointer to output file + */ + g_init_bits = init_bits; + g_outfile = outfile; + + /* Set up the necessary values */ + clear_flg = 0; + cur_accum = 0; + cur_bits = 0; + maxbits = GIFBITS; + maxcode = MAXCODE(n_bits = g_init_bits); + + ClearCode = (1 << (init_bits - 1)); + EOFCode = ClearCode + 1; + free_ent = ClearCode + 2; + + char_init(); + for (i=0; i<HSIZE; i++) { + htab[i] = 0; + codetab[i] = 0; + } + + ent = GIFNextPixel (); + + hshift = 0; + for (fcode = (long) hsize; fcode < 65536L; fcode *= 2L) + ++hshift; + hshift = 8 - hshift; /* set hash code range bound */ + + hsize_reg = hsize; + cl_hash ((count_int) hsize_reg); /* clear hash table */ + + output ((code_int)ClearCode); + + while ((c = GIFNextPixel ()) != EOF) { + + fcode = (long) (((long) c << maxbits) + ent); + i = (((code_int)c << hshift) ^ ent); /* xor hashing */ + + if (HashTabOf (i) == fcode) { + ent = CodeTabOf (i); + continue; + } else if ((long)HashTabOf (i) < 0) /* empty slot */ + goto nomatch; + disp = hsize_reg - i; /* secondary hash (after G. Knott) */ + if (i == 0) + disp = 1; +probe: + if ((i -= disp) < 0) + i += hsize_reg; + + if (HashTabOf (i) == fcode) { + ent = CodeTabOf (i); + continue; + } + if ((long)HashTabOf (i) > 0) + goto probe; +nomatch: + output ((code_int) ent); + ent = c; + if (free_ent < maxmaxcode) { /* } */ + CodeTabOf (i) = free_ent++; /* code -> hashtable */ + HashTabOf (i) = fcode; + } else + cl_block(); + } + + /* + * Put out the final code. + */ + output ((code_int)ent); + output ((code_int) EOFCode); +} + +/* + * Output the given code. + * Inputs: + * code: A n_bits-bit integer. If == -1, then EOF. This assumes + * that n_bits =< (long)wordsize - 1. + * Outputs: + * Outputs code to the file. + * Assumptions: + * Chars are 8 bits long. + * Algorithm: + * Maintain a GIFBITS character long buffer (so that 8 codes will + * fit in it exactly). Use the VAX insv instruction to insert each + * code in turn. When the buffer fills up empty it and start over. + */ + +static void +output (code) +code_int code; +{ + cur_accum &= masks[ cur_bits ]; + + if (cur_bits > 0) + cur_accum |= ((long)code << cur_bits); + else + cur_accum = code; + + cur_bits += n_bits; + + while (cur_bits >= 8) { + char_out ((unsigned int)(cur_accum & 0xff)); + cur_accum >>= 8; + cur_bits -= 8; + } + + /* + * If the next entry is going to be too big for the code size, + * then increase it, if possible. + */ + if (free_ent > maxcode || clear_flg) { + + if (clear_flg) { + maxcode = MAXCODE (n_bits = g_init_bits); + clear_flg = 0; + } else { + ++n_bits; + if (n_bits == maxbits) + maxcode = maxmaxcode; + else + maxcode = MAXCODE(n_bits); + } + } + + if (code == EOFCode) { + /* At EOF, write the rest of the buffer. */ + while (cur_bits > 0) { + char_out ((unsigned int)(cur_accum & 0xff)); + cur_accum >>= 8; + cur_bits -= 8; + } + flush_char(); + fflush (g_outfile); + if (ferror (g_outfile)) + perror ("error writing output file"); + } +} + +/* + * Clear out the hash table + */ +static void +cl_block () /* table clear for block compress */ +{ + + cl_hash ((count_int) hsize); + free_ent = ClearCode + 2; + clear_flg = 1; + + output ((code_int)ClearCode); +} + +static void +cl_hash(hsize) /* reset code table */ +register count_int hsize; +{ + + register count_int *htab_p = htab + hsize; + + register long i; + register long m1 = -1; + + i = hsize - 16; + do { /* might use Sys V memset(3) here */ + *(htab_p - 16) = m1; + *(htab_p - 15) = m1; + *(htab_p - 14) = m1; + *(htab_p - 13) = m1; + *(htab_p - 12) = m1; + *(htab_p - 11) = m1; + *(htab_p - 10) = m1; + *(htab_p - 9) = m1; + *(htab_p - 8) = m1; + *(htab_p - 7) = m1; + *(htab_p - 6) = m1; + *(htab_p - 5) = m1; + *(htab_p - 4) = m1; + *(htab_p - 3) = m1; + *(htab_p - 2) = m1; + *(htab_p - 1) = m1; + htab_p -= 16; + } while ((i -= 16) >= 0); + + for (i += 16; i > 0; --i) + *--htab_p = m1; +} + +/* Set up the 'byte output' routine + */ +static void +char_init() +{ + register int i; + + a_count = 0; + for (i=0; i<256; i++) + accum[i] = 0; +} + +/* Add a character to the end of the current packet, and if it is 254 + * characters, flush the packet to disk. + */ +static void +char_out (c) +int c; +{ + accum[ a_count++ ] = c; + if (a_count >= 254) + flush_char(); +} + +/* Flush the packet to disk, and reset the accumulator */ +static void +flush_char() +{ + if (a_count > 0) { + fputc (a_count, g_outfile); + fwrite (accum, 1, a_count, g_outfile); + a_count = 0; + } +} diff --git a/unix/gdev/sgidev/sgi2svg.c b/unix/gdev/sgidev/sgi2svg.c new file mode 100644 index 00000000..be25a704 --- /dev/null +++ b/unix/gdev/sgidev/sgi2svg.c @@ -0,0 +1,245 @@ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* +** SGI2SVG.C -- Read IRAF SGI metacode from standard input, translate into +** Scalable Vector Graphics (SVG) format. +** +** Usage +** sgi2svg.e [-params] [sgi_metacode] [| lpr -Papple] +** +** -fg <N> FG color specified as RGB triplet (e.g. 'F00' is red) +** -bg <N> BG color specified as RGB triplet (e.g. '0F0' is green) +** -fill <N> fill color specified as RGB triplet (e.g. '00F' is blue) +** -w <N> width of plot, device pixels starting from l +** -h <N> height of plot, device pixels starting from b +** -p <N> pen width +** +** Option values must be separated from their flags by a space; the input +** file name and the switches may occur in any order. +** +** Sample Graphcap: +** +** g-svg|UNIX generic interface to SVG file generator:\ +** :DD=usvg,tmp$sgk,!{ sgidispatch sgi2svg -w $(PX) -h $(PY) \ +** -bg FFF -fg 000 -fill FFF $F > sgi$$.svg ; }&:PX#640:PY#480:\ +** :kf=bin$x_sgikern.e:tn=sgikern:tc=sgi_apl: +*/ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define GKI_MAXNDC 32767. /* SGK units */ + + +/* Device opcodes and parameters. + */ +#define DEF_LEFT 0 /* origin in device pixels in x */ +#define DEF_BOTTOM 0 /* origin in device pixels in y */ +#define DEF_WIDTH 640 /* width in x (240d/i, 11" paper) */ +#define DEF_HEIGHT 480 /* height in y (240d/i, 8.5" paper)*/ +#define DEF_PENWIDTH 1 /* origin in device pixels in x */ + + +/* Commands to setup SVG environment. +*/ +static char *svg_prolog[] = { + "<?xml version=\"1.0\" standalone=\"no\"?>\n", + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", + " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", + NULL +}; + +/* Opcode instruction. +*/ +struct sgi_inst { + short opcode; + short x, y; +}; + + +int pen_width = DEF_PENWIDTH; /* initial line width */ +int width = DEF_WIDTH; /* margins */ +int height = DEF_HEIGHT; +char *bg = "#FFF"; /* BG/FG colors */ +char *fg = "#000"; +char *fill = "#FFF"; /* vector fill color */ + + +static void translate (FILE *in, FILE *out); + + + +/* MAIN -- Main entry point for SGI2UHPGL. Optional arguments are device +** window parameters and name of input file. +*/ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile = "stdin", *argp; + int argno; + register char **lp; + + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case 'f': + if (argp[2] == 'g') + fg = argv[++argno]; + else + fill = argv[++argno]; + break; + case 'b': + bg = argv[++argno]; + break; + case 'w': width = atoi (argv[++argno]); break; + case 'h': height = atoi (argv[++argno]); break; + case 'p': pen_width = atoi (argv[++argno]); break; + default: + break; + } + + } else { + /* Input sgi-metacode file specification. + */ + infile = argp; + } + } + + + /* Open the input file. */ + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2svg): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + + /* Output the standard prolog. + */ + for (lp=svg_prolog; *lp; lp++) + fputs (*lp, stdout); + + fprintf (stdout,"<svg width=\"%dpx\" height=\"%dpx\" version=\"1.1\"\n", + width, height); + fprintf (stdout," xmlns=\"http://www.w3.org/2000/svg\">"); + fprintf (stdout, + "<g id=\"g0\" fill=\"#%s\" stroke=\"#%s\" stroke-width=\"1\">\n", + bg, fg); + fprintf (stdout, + "<rect x=\"1\" y=\"1\" width=\"%d\" height=\"%d\"\n", + width, height); + fprintf (stdout, + " fill=\"#%s\" stroke=\"#%s\" stroke-width=\"1\"/>\n", fill, bg); + + + + /* Process the metacode. + */ + translate (in, stdout); + + + /* Clean up. + */ + fprintf (stdout, "</g></svg>"); /* output the end of file */ + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into device +** instructions and write to stdout. +*/ +static void +translate (FILE *in, FILE *out) +{ + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + int n, in_stroke=0, swap_bytes = isSwapped(); + int x, y, gnum=1; + + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + fprintf (out, "\n"); + break; + + case SGK_MOVE: + x = (int) (((float)sgip->x / GKI_MAXNDC) * width); + y = (int) (((float)sgip->y / GKI_MAXNDC) * height); + y = height - y + 1; + if (in_stroke) /* end current stroke */ + fprintf (out, "\"/>"); + + /* Begin a new output stroke. + */ + fprintf (out, "<polyline points=\"%d,%d", x, y); + in_stroke = 1; + break; + + case SGK_DRAW: + x = (int) (((float)sgip->x / GKI_MAXNDC) * width); + y = (int) (((float)sgip->y / GKI_MAXNDC) * height); + y = height - y + 1; + fprintf (out, " %d,%d", x, y); + in_stroke = 1; + break; + + case SGK_SETLW: + /* Set pen width. + */ + pen_width = sgip->x + 1; + if (in_stroke) /* end current stroke */ + fprintf (out, "\"/></g>"); + fprintf (out, "<g id=\"g%d\" stroke-width=\"%d\">", + gnum++, pen_width); + in_stroke = 0; + break; + + default: + fprintf (stderr, "sgi2svg: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Terminate plotting and exit. + */ + fprintf (out, " \"/></g>\n"); +} diff --git a/unix/gdev/sgidev/sgi2uapl.c b/unix/gdev/sgidev/sgi2uapl.c new file mode 100644 index 00000000..3c59d284 --- /dev/null +++ b/unix/gdev/sgidev/sgi2uapl.c @@ -0,0 +1,545 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <time.h> +#include <pwd.h> + +#ifdef SOLARIS +#include <sys/systeminfo.h> +#endif + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UAPL.C -- Read IRAF SGI metacode from standard input, translate into + * Postscript for the Apple Laserwriter and write to standard output. + * + * Usage: + * + * sgi2uapl.e [-params] [sgi_metacode] [| lpr -Plw] + * + * -4 use 4 byte point encoding scheme (default is 7 byte) + * -t omit the timestamp/logo normally written to corner of plot + * -l N left edge; x plot origin in device pixels + * -b N bottom edge; y plot origin in device pixels + * -w N width of plot, device pixels starting from l + * -h N height of plot, device pixels starting from b + * -p O.S pen width `origin' and `slope' + * + * Numeric values may be appended directly to their flags or separated by a + * space; the input file name and the switches may occur in any order. + * Note that you can arrange for the Postscript output to be saved in a file + * as well as directed to the printer by calling the translator as + * + * sgi2uapl.e [params] | tee -a file | lpr -Plw + */ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define SGK_MAXNDC 32767 /* SGK units */ + +/* Device opcodes and parameters. The default edge and width parameters (DEF_) + * are given in Apple Laserwriter pixels, at 300 dots/inch. Although bypassing + * the device-independence of Postscript, this achieves greater efficiency + * both in translator performance and in transmission rate to the plotter. + * The device y-origin is at the lower left corner of the page, but we take + * care of this with a Postscript coordinate transformation. Thus the maximum + * page `width' is 11*300 pixels, `height' is 8.5*300 pixels. + */ +#define DEV_FRAME "showpage setcoords setjoins\n" /* newframe */ +#define DEV_SETLW "setlinewidth\n" /* linewidth */ + +#define MAX_POINTS 512 /* maximum points on stack before a STROKE */ +#define DEF_LEFT 30 /* origin in device pixels in x */ +#define DEF_WIDTH 3180 /* width in x (300d/i, 11" paper) */ +#define DEF_BOTTOM 60 /* origin in device pixels in y */ +#define DEF_HEIGHT 2415 /* height in y (300d/i, 8.5" paper) */ +#define DEF_PENBASE 3 /* base pen width (LW 1->2) */ +#define DEF_PENSLOPE 4 /* pen width slope (LW 2->4, 3->6 etc.) */ +#define SZ_PENCMD 16 /* total no. of chars in penwidth instruction */ +#define SZ_PENVAL 2 /* no. of chars in penwidth value */ +#define SZ_VCODE 7 /* no. of chars in MOVE or DRAW opcode */ +#define SZ_VECT 17 /* total no. chars in a MOVE or DRAW inst. */ +#define SZ_COORD 4 /* no. of chars in device coordinate */ +#define XY_MOVE 0 +#define XY_DRAW 1 + +struct sgi_inst { + short opcode; + short x; + short y; +}; + +/* Commands to setup Postscript environment. + */ +static char *ps_init[] = { + "%!PS-Adobe-2.0", + "/devppi 300 def", + "/userppi 72 def", + "/pagewidth 8.5 def", + "/devpixtouser { userppi mul devppi div } def", + "/pagetolandscape 90 def", + "/setcoords { pagewidth userppi mul 0 translate", + " pagetolandscape rotate 1 devpixtouser 1 devpixtouser scale } def", + "/setjoins { 1 setlinejoin 1 setlinecap } def", + "erasepage initgraphics setcoords setjoins", + NULL }; + +/* 7BYTE -- Postscript procedures to move or draw, with the X,Y coordinates + * encoded as a 4 byte sequence (7 bytes including the command name and spaces) + * following the command name. This is the fastest encoding, since it + * minimizes the Postscript interpreter execution time. + * + * bit 76543210 + * ------------------------------------------ + * 0 01XXXXXX hi 6 X bits + * 1 01XXXXXX li 6 X bits + * 2 01YYYYYY hi 6 Y bits + * 3 01YYYYYY lo 6 Y bits + */ +static char *ps_7byte[] = { + "/getpoint {", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " } def", + "/m { getpoint moveto } def", + "/d { getpoint lineto } def", + NULL }; + +/* 4BYTE -- Postscript procedure to draw an arbitrary series of vectors, + * encoded 4 bytes per point. This is the most space efficient encoding, + * but the runtime may be somewhat longer than for the 7byte encoding, + * due to the Postscript interpreter overhead. + * + * Optional Flag byte: + * > move instruction + * + draw instruction + * $ terminate plotting + * other ignored (e.g., whitespace) + * + * Point Encoding: + * bit 76543210 + * ------------------------------------------ + * 1 01XXXXXX hi 6 X bits + * 2 01XXXXXX lo 6 X bits + * 3 01YYYYYY hi 6 Y bits + * 4 01YYYYYY lo 6 Y bits + * + * Data points are encoded 12 bits (0-4095) per X,Y coordinate. The flag byte + * is used as the terminator, to toggle the move/draw state, and to permit + * whitespace to be ignored. A high bit is set in each byte to ensure a + * printable character, as control codes would interfere with the operation of + * the Postscript interpreter. + */ +#define CH_MOVE '>' +#define CH_DRAW '+' +#define CH_EXITPLOT '$' + +static char *ps_4byte[] = { + "/plot { /movepen { moveto } def", + " { currentfile read not { exit } if", + " { dup 8#100 ge", + " { exit }", + " { dup 8#076 eq", + " { pop /movepen { moveto } def", + " currentfile read not { exit } if }", + " { dup 8#053 eq", + " { pop /movepen { lineto } def", + " currentfile read not { exit } if }", + " { dup 8#044 eq", + " { exit }", + " { pop currentfile read not { exit } if }", + " ifelse }", + " ifelse }", + " ifelse }", + " ifelse", + " } loop", + " dup 8#044 eq { pop exit } { 8#77 and 6 bitshift } ifelse", + " currentfile read pop 8#77 and or", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " movepen", + " } loop", + " } def", + NULL }; + +static int fourbyte = 0; +static int penmode = -1; +static int omit_logo = 0; +static int dev_left; +static int dev_bottom; +static int dev_width; +static int dev_height; +static int dev_penbase = DEF_PENBASE; +static int dev_penslope = DEF_PENSLOPE; +static int npts = 0; + + +static void translate (FILE *in, FILE *out); +static char *make_label (void); +static void textout (FILE *out, char *text[]); +static char *penencode (int val, char *code); +static void xy_flush (FILE *out); +static void xy_point (FILE *out, register int x, register int y, int flag); + + + +/* MAIN -- Main entry point for SGI2UAPL. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + char *argp; + int argno; + int np; + char penparam[SZ_PENCMD]; + + + infile = "stdin"; + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case '4': + fourbyte++; + break; + case 't': + omit_logo++; + break; + case 'l': + dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT); + break; + case 'b': + dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM); + break; + case 'w': + dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH); + break; + case 'h': + dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT); + break; + case 'p': + if (argp[2] == (char) 0) + if (argv[argno+1] == NULL) { + fprintf (stderr, "missing arg to switch `%s';", + argp); + fprintf (stderr, " reset to %d.%d\n", dev_penbase, + dev_penslope); + } else + strcpy (penparam, argv[++argno]); + else + strcpy (penparam, argv[argno]+2); + + np = sscanf (penparam, "%d . %d", &dev_penbase, + &dev_penslope); + if (np == 1) { + dev_penslope = dev_penbase; + } else if (np < 1) { + dev_penbase = DEF_PENBASE; + dev_penslope = DEF_PENSLOPE; + } + + break; + default: + fprintf (stderr, "sgi2uapl: unknown switch '%s'\n", argp); + } + + } else { + /* Input sgi-metacode file specification. + */ + infile = argp; + } + } + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2uapl): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the metacode. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into device + * instructions and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + int n, x, y, curpoints = 0, swap_bytes; + float xscale, yscale; + + + swap_bytes = isSwapped(); + + xscale = (float) dev_width / (float) SGK_MAXNDC; + yscale = (float) dev_height / (float) SGK_MAXNDC; + + /* Output device initialization. */ + textout (out, ps_init); + + /* Define the Postscript plotting procedures. */ + if (fourbyte) + textout (out, ps_4byte); + else + textout (out, ps_7byte); + + /* Initialize pen width. */ + fwrite (penencode (dev_penbase, DEV_SETLW), SZ_PENCMD, 1, out); + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + xy_flush (out); + fprintf (out, DEV_FRAME); + break; + + case SGK_MOVE: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + xy_point (out, x, y, XY_MOVE); + break; + + case SGK_DRAW: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + xy_point (out, x, y, XY_DRAW); + + /* Limit number of points passed to Postscript between + * 'stroke' commands to draw the buffered points. + */ + curpoints = curpoints + 1; + if (curpoints > MAX_POINTS) { + xy_flush (out); + xy_point (out, x, y, XY_MOVE); + curpoints = 0; + } + break; + + case SGK_SETLW: { + /* Set pen width. + */ + int x = max (0, sgip->x - 1); + + xy_flush (out); + curpoints = 0; + fwrite (penencode ( + max (1, dev_penbase + x * dev_penslope), DEV_SETLW), + SZ_PENCMD, 1, out); + } + break; + + default: + fprintf (stderr, "sgi2uapl: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Terminate plotting and exit. + */ + xy_flush (out); + + /* Add the NOAO logo and timestamp at the bottom of the page and + * output the page. + */ + if (!omit_logo) { + fprintf (out, "/Times-Roman findfont 24 scalefont setfont\n"); + + /* fprintf (out, "[-1 0 0 -1 2350 3180] setmatrix\n"); */ + fprintf (out, "initmatrix\n"); + fprintf (out, "-1 72 mul 300 div 1 72 mul 300 div scale\n"); + fprintf (out, "-2409 88 translate\n"); + + fprintf (out, "%d %d moveto\n", 1600, 3150); + fprintf (out, "[1 0 0 -1 0 0] concat\n"); + fprintf (out, "(%s) show\n", make_label()); + } + + fprintf (out, "showpage\n"); +} + + +/* XY_POINT -- Output a move or draw instruction, using either the 4 byte or + * 7 byte encoding scheme. + */ +static void +xy_point ( + FILE *out, /* output file */ + register int x, /* coords to move to */ + register int y, /* coords to move to */ + int flag /* move or draw? */ +) +{ + static char o[] = "m XXXX"; + register char *op = o; + register int n; + + if (fourbyte) { + if (npts == 0) { + fputs ("plot\n", out); + penmode = XY_MOVE; + } + + if (flag != penmode) + *op++ = ((penmode = flag) == XY_MOVE) ? CH_MOVE : CH_DRAW; + + *op++ = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = (x & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = (y & 077)) == 077) ? n : (0100 | n); + + fwrite (o, op-o, 1, out); + if (!(++npts % 15)) + fputc ('\n', out); + + } else { + o[0] = (flag == XY_MOVE) ? 'm' : 'd'; + o[2] = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n); + o[3] = ((n = (x & 077)) == 077) ? n : (0100 | n); + o[4] = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n); + o[5] = ((n = (y & 077)) == 077) ? n : (0100 | n); + + fwrite (o, 6, 1, out); + if (!(++npts % 10)) + fputc ('\n', out); + else + fputc (' ', out); + } +} + + +/* XY_FLUSH -- Terminate the current drawing sequence, if any, and issue the + * stroke command to Postscript to draw the buffered points. + */ +static void +xy_flush (FILE *out) +{ + if (npts > 0) { + if (fourbyte) + fputs ("$\n", out); + else if (npts % 10) + fputc ('\n', out); + fputs ("stroke\n", out); + npts = 0; + } +} + + +/* PENENCODE -- Encode base, slope into a character string formatted for the + * device set-pen command. + */ +static char * +penencode ( + int val, /* device line width */ + char *code /* device set-linewidth command */ +) +{ + static char obuf[SZ_PENCMD+1]; + register int digit, n; + register char *op, *ip; + + for (op = &obuf[SZ_PENVAL-1], digit = SZ_PENVAL, n=val; --digit >= 0; + n = n / 10) + *op-- = n % 10 + '0'; + obuf[SZ_PENVAL] = ' '; + for (op = &obuf[SZ_PENVAL+1], ip = code, n = SZ_PENCMD; --n >= 0; ) + *op++ = *ip++; + + return (obuf); +} + + +/* TEXTOUT -- Output lines of text to a file. + */ +static void +textout ( + FILE *out, /* output file */ + char *text[] /* array of lines of text */ +) +{ + register char **lp; + + for (lp=text; *lp; lp++) { + fputs (*lp, out); + fputc ('\n', out); + } +} + + +/* MAKE_LABEL -- Generate the label for the output printer page. + */ +static char * +make_label (void) +{ + static char buf[128]; + char hostname[32]; + char username[32]; + struct passwd *pw; + time_t clock; + +#ifdef SOLARIS + sysinfo (SI_HOSTNAME, hostname, 32); +#else + gethostname (hostname, 32); +#endif + + clock = time(0); + pw = getpwuid (getuid()); + strcpy (username, pw->pw_name); + endpwent(); + + sprintf (buf, "NOAO/IRAF %s@%s %s", + username, hostname, asctime(localtime(&clock))); + + return (buf); +} diff --git a/unix/gdev/sgidev/sgi2ueps.c b/unix/gdev/sgidev/sgi2ueps.c new file mode 100644 index 00000000..345eb702 --- /dev/null +++ b/unix/gdev/sgidev/sgi2ueps.c @@ -0,0 +1,530 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <ctype.h> +#include <time.h> +#include <pwd.h> +#include <string.h> +#include <stdlib.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UEPS.C -- Read IRAF SGI metacode from standard input, translate into + * Encapsulated Postscript and write to standard output. + * + * Usage: + * + * sgi2ueps.e [-params] [sgi_metacode] [| lpr -Plw] + * + * -4 use 4 byte point encoding scheme (default is 7 byte) + * -l N left edge; x plot origin in device pixels + * -b N bottom edge; y plot origin in device pixels + * -w N width of plot, device pixels starting from l + * -h N height of plot, device pixels starting from b + * -p O.S pen width `origin' and `slope' + * + * Numeric values may be appended directly to their flags or separated by a + * space; the input file name and the switches may occur in any order. + * Note that you can arrange for the Postscript output to be saved in a file + * as well as directed to the printer by calling the translator as + * + * sgi2ueps.e [params] | tee -a file | lpr -Plw + */ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define SGK_MAXNDC 32767 /* SGK units */ + +/* Device opcodes and parameters. The default edge and width parameters (DEF_) + * are given in pixels at 300 dots/inch. Although bypassing the + * device-independence of Postscript, this achieves greater efficiency + * both in translator performance and in transmission rate to the plotter. + * The device y-origin is at the lower left corner of the page, but we take + * care of this with a Postscript coordinate transformation. Thus the maximum + * page `width' is 11*300 pixels, `height' is 8.5*300 pixels. + */ +#define DEV_FRAME "showpage setcoords setjoins\n" /* newframe */ +#define DEV_SETLW "setlinewidth\n" /* linewidth */ + +#define MAX_POINTS 512 /* maximum points on stack before a STROKE */ +#define DEF_LEFT 30 /* origin in device pixels in x */ +#define DEF_WIDTH 3180 /* width in x (300d/i, 11" paper) */ +#define DEF_BOTTOM 60 /* origin in device pixels in y */ +#define DEF_HEIGHT 2415 /* height in y (300d/i, 8.5" paper) */ +#define DEV_UNITS 300 /* EPS translator units: N per inch */ +#define EPS_UNITS 72 /* PostScript units (points) */ +#define DEF_PENBASE 3 /* base pen width (LW 1->2) */ +#define DEF_PENSLOPE 4 /* pen width slope (LW 2->4, 3->6 etc.) */ +#define SZ_PENCMD 16 /* total no. of chars in penwidth instruction */ +#define SZ_PENVAL 2 /* no. of chars in penwidth value */ +#define SZ_VCODE 7 /* no. of chars in MOVE or DRAW opcode */ +#define SZ_VECT 17 /* total no. chars in a MOVE or DRAW inst. */ +#define SZ_COORD 4 /* no. of chars in device coordinate */ +#define XY_MOVE 0 +#define XY_DRAW 1 + +struct sgi_inst { + short opcode; + short x; + short y; +}; + +/* Commands to setup Postscript environment. + */ +static char *ps_init[] = { + "/devppi 300 def", + "/userppi 72 def", + "/pagewidth 8.5 def", + "/devpixtouser { userppi mul devppi div } def", + "/setscale { 1 devpixtouser 1 devpixtouser scale } def", + "/pagetolandscape 90 def", + "/setcoords { pagewidth userppi mul 0 translate", + " pagetolandscape rotate setscale } def", + "/setjoins { 1 setlinejoin 1 setlinecap } def", + NULL }; + +static char *ps_endprolog[] = { + "%%EndProlog", + "%%Page: 1 1", + "gsave setscale setjoins", + NULL }; + +/* 7BYTE -- Postscript procedures to move or draw, with the X,Y coordinates + * encoded as a 4 byte sequence (7 bytes including the command name and spaces) + * following the command name. This is the fastest encoding, since it + * minimizes the Postscript interpreter execution time. + * + * bit 76543210 + * ------------------------------------------ + * 0 01XXXXXX hi 6 X bits + * 1 01XXXXXX li 6 X bits + * 2 01YYYYYY hi 6 Y bits + * 3 01YYYYYY lo 6 Y bits + */ +static char *ps_7byte[] = { + "/getpoint {", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " } def", + "/m { getpoint moveto } def", + "/d { getpoint lineto } def", + NULL }; + +/* 4BYTE -- Postscript procedure to draw an arbitrary series of vectors, + * encoded 4 bytes per point. This is the most space efficient encoding, + * but the runtime may be somewhat longer than for the 7byte encoding, + * due to the Postscript interpreter overhead. + * + * Optional Flag byte: + * > move instruction + * + draw instruction + * $ terminate plotting + * other ignored (e.g., whitespace) + * + * Point Encoding: + * bit 76543210 + * ------------------------------------------ + * 1 01XXXXXX hi 6 X bits + * 2 01XXXXXX lo 6 X bits + * 3 01YYYYYY hi 6 Y bits + * 4 01YYYYYY lo 6 Y bits + * + * Data points are encoded 12 bits (0-4095) per X,Y coordinate. The flag byte + * is used as the terminator, to toggle the move/draw state, and to permit + * whitespace to be ignored. A high bit is set in each byte to ensure a + * printable character, as control codes would interfere with the operation of + * the Postscript interpreter. + */ +#define CH_MOVE '>' +#define CH_DRAW '+' +#define CH_EXITPLOT '$' + +static char *ps_4byte[] = { + "/plot { /movepen { moveto } def", + " { currentfile read not { exit } if", + " { dup 8#100 ge", + " { exit }", + " { dup 8#076 eq", + " { pop /movepen { moveto } def", + " currentfile read not { exit } if }", + " { dup 8#053 eq", + " { pop /movepen { lineto } def", + " currentfile read not { exit } if }", + " { dup 8#044 eq", + " { exit }", + " { pop currentfile read not { exit } if }", + " ifelse }", + " ifelse }", + " ifelse }", + " ifelse", + " } loop", + " dup 8#044 eq { pop exit } { 8#77 and 6 bitshift } ifelse", + " currentfile read pop 8#77 and or", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " movepen", + " } loop", + " } def", + NULL }; + +static int npts = 0; +static int fourbyte = 0; +static int penmode = -1; +static int dev_left; +static int dev_bottom; +static int dev_width; +static int dev_height; +static int dev_penbase = DEF_PENBASE; +static int dev_penslope = DEF_PENSLOPE; +static char progname[SZ_LINE+1]; + +static void translate (FILE *in, FILE *out); +static void xy_point (FILE *out, register int x, register int y, int flag); +static void xy_flush (FILE *out); +static char *penencode (int val, char *code); +static void textout (FILE *out, char *text[]); +static void eps_comments (FILE *out); + + + +/* MAIN -- Main entry point for SGI2UAPL. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + char *argp; + int argno; + int np; + char penparam[SZ_PENCMD]; + + + strcpy (progname, argv[0]); + infile = "stdin"; + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case '4': + fourbyte++; + break; + case 'l': + dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT); + break; + case 'b': + dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM); + break; + case 'w': + dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH); + break; + case 'h': + dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT); + break; + case 'p': + if (argp[2] == (char) 0) + if (argv[argno+1] == NULL) { + fprintf (stderr, "missing arg to switch `%s';", + argp); + fprintf (stderr, " reset to %d.%d\n", dev_penbase, + dev_penslope); + } else + strcpy (penparam, argv[++argno]); + else + strcpy (penparam, argv[argno]+2); + + np = sscanf (penparam, "%d . %d", &dev_penbase, + &dev_penslope); + if (np == 1) { + dev_penslope = dev_penbase; + } else if (np < 1) { + dev_penbase = DEF_PENBASE; + dev_penslope = DEF_PENSLOPE; + } + + break; + default: + fprintf (stderr, "sgi2ueps: unknown switch '%s'\n", argp); + } + + } else { + /* Input sgi-metacode file specification. + */ + infile = argp; + } + } + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2ueps): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the metacode. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into device + * instructions and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + int n, x, y, curpoints = 0, swap_bytes; + float xscale, yscale; + + + swap_bytes = isSwapped(); + + xscale = (float) dev_width / (float) SGK_MAXNDC; + yscale = (float) dev_height / (float) SGK_MAXNDC; + + /* Output device initialization. */ + eps_comments (out); + textout (out, ps_init); + + /* Define the Postscript plotting procedures. */ + if (fourbyte) + textout (out, ps_4byte); + else + textout (out, ps_7byte); + + textout (out, ps_endprolog); + + /* Initialize pen width. */ + fwrite (penencode (dev_penbase, DEV_SETLW), SZ_PENCMD, 1, out); + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + xy_flush (out); + fprintf (out, DEV_FRAME); + break; + + case SGK_MOVE: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + xy_point (out, x, y, XY_MOVE); + break; + + case SGK_DRAW: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + xy_point (out, x, y, XY_DRAW); + + /* Limit number of points passed to Postscript between + * 'stroke' commands to draw the buffered points. + */ + curpoints = curpoints + 1; + if (curpoints > MAX_POINTS) { + xy_flush (out); + xy_point (out, x, y, XY_MOVE); + curpoints = 0; + } + break; + + case SGK_SETLW: { + /* Set pen width. + */ + int x = max (0, sgip->x - 1); + + xy_flush (out); + curpoints = 0; + fwrite (penencode ( + max (1, dev_penbase + x * dev_penslope), DEV_SETLW), + SZ_PENCMD, 1, out); + } + break; + + default: + fprintf (stderr, "sgi2ueps: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Terminate plotting and exit. + */ + xy_flush (out); + + fprintf (out, "grestore showpage\n"); +} + + +/* XY_POINT -- Output a move or draw instruction, using either the 4 byte or + * 7 byte encoding scheme. + */ +static void +xy_point ( + FILE *out, /* output file */ + register int x, /* coords to move to */ + register int y, /* coords to move to */ + int flag /* move or draw? */ +) +{ + static char o[] = "m XXXX"; + register char *op = o; + register int n; + + if (fourbyte) { + if (npts == 0) { + fputs ("plot\n", out); + penmode = XY_MOVE; + } + + if (flag != penmode) + *op++ = ((penmode = flag) == XY_MOVE) ? CH_MOVE : CH_DRAW; + + *op++ = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = (x & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = (y & 077)) == 077) ? n : (0100 | n); + + fwrite (o, op-o, 1, out); + if (!(++npts % 15)) + fputc ('\n', out); + + } else { + o[0] = (flag == XY_MOVE) ? 'm' : 'd'; + o[2] = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n); + o[3] = ((n = (x & 077)) == 077) ? n : (0100 | n); + o[4] = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n); + o[5] = ((n = (y & 077)) == 077) ? n : (0100 | n); + + fwrite (o, 6, 1, out); + if (!(++npts % 10)) + fputc ('\n', out); + else + fputc (' ', out); + } +} + + +/* XY_FLUSH -- Terminate the current drawing sequence, if any, and issue the + * stroke command to Postscript to draw the buffered points. + */ +static void +xy_flush (FILE *out) +{ + if (npts > 0) { + if (fourbyte) + fputs ("$\n", out); + else if (npts % 10) + fputc ('\n', out); + fputs ("stroke\n", out); + npts = 0; + } +} + + +/* PENENCODE -- Encode base, slope into a character string formatted for the + * device set-pen command. + */ +static char * +penencode ( + int val, /* device line width */ + char *code /* device set-linewidth command */ +) +{ + static char obuf[SZ_PENCMD+1]; + register int digit, n; + register char *op, *ip; + + for (op = &obuf[SZ_PENVAL-1], digit = SZ_PENVAL, n=val; --digit >= 0; + n = n / 10) + *op-- = n % 10 + '0'; + obuf[SZ_PENVAL] = ' '; + for (op = &obuf[SZ_PENVAL+1], ip = code, n = SZ_PENCMD; --n >= 0; ) + *op++ = *ip++; + + return (obuf); +} + + +/* TEXTOUT -- Output lines of text to a file. + */ +static void +textout ( + FILE *out, /* output file */ + char *text[] /* array of lines of text */ +) +{ + register char **lp; + + for (lp=text; *lp; lp++) { + fputs (*lp, out); + fputc ('\n', out); + } +} + + +/* EPS_COMMENTS -- Set identifying comments for EPS conformance. + */ +static void +eps_comments (FILE *out) +{ + time_t clock; + int llx, lly, urx, ury; + + clock = time(0); + + fprintf (out, "%%!PS-Adobe-3.0 EPSF-3.0\n"); + fprintf (out, "%%%%Title: IRAF SGI plot\n"); + fprintf (out, "%%%%Creator: %s\n", progname); + fprintf (out, "%%%%CreationDate: %s", asctime(localtime(&clock))); + + /* Compute bounding box in PostScript coordinates. */ + llx = ((float) dev_left / (float) DEV_UNITS) * (float) EPS_UNITS; + lly = ((float) dev_bottom / (float) DEV_UNITS) * (float) EPS_UNITS; + urx = ((float) (dev_left + dev_width) / (float) DEV_UNITS) + * (float) EPS_UNITS; + ury = ((float) (dev_bottom + dev_height) / (float) DEV_UNITS) + * (float) EPS_UNITS; + + fprintf (out, "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury); + fprintf (out, "%%%%Pages: 1\n"); + fprintf (out, "%%%%EndComments\n"); +} diff --git a/unix/gdev/sgidev/sgi2uhpgl.c b/unix/gdev/sgidev/sgi2uhpgl.c new file mode 100644 index 00000000..2e952446 --- /dev/null +++ b/unix/gdev/sgidev/sgi2uhpgl.c @@ -0,0 +1,160 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UHPGL.C -- Read IRAF SGI metacode from standard input, translate into + * HP graphics language call for HP 7550A plotter + * + * Usage + * sgi2uhpgl.e [sgi_metacode] [| lpr -Papple] + * + */ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define GKI_MAXNDC 32767 /* SGK units */ + +/* Device opcodes and parameters. + */ +#define DEV_INIT "IN;DF;SP1;" /* initialize */ +#define DEV_END "SP0;PG:" /* terminate */ +#define DEV_FRAME "PG;" /* newframe */ +#define DEV_MOVE "PU" /* move */ +#define DEV_DRAW "PD" /* draw */ +#define PRES 1016 /* plotter resolution per inch */ +#define XLEN_INCHES 10.0 /* width of plot (x) in inches */ +#define YLEN_INCHES 8.0 /* height of plot (y) in inches */ +#define XSCALE PRES * XLEN_INCHES / GKI_MAXNDC +#define YSCALE PRES * YLEN_INCHES / GKI_MAXNDC + + +#define SZ_COORD 4 /* no. of chars in device coordinate */ + +struct sgi_inst { + short opcode; + short x; + short y; +}; + +static void translate (FILE *in, FILE *out); + + +/* MAIN -- Main entry point for SGI2UHPGL. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + + + infile = "stdin"; + + /* Process the command line. + */ + infile = argv[1]; + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2uhpp): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the metacode. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into device + * instructions and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + int n, swap_bytes; + float x, y; + + + swap_bytes = isSwapped(); + + /* Output device initialization. + */ + fprintf (out, "%s\n", DEV_INIT); + + /* Initialize pen width. Not implemented. + */ + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + fprintf (out, "%s\n", DEV_FRAME); + break; + + case SGK_MOVE: + x = sgip->x * XSCALE; + y = sgip->y * YSCALE; + fprintf (out, + "%s%06.0f%s%06.0f%s\n", DEV_MOVE, x, ",", y, ";"); + break; + + case SGK_DRAW: + x = sgip->x * XSCALE; + y = sgip->y * YSCALE; + fprintf (out, + "%s%06.0f%s%06.0f%s\n", DEV_DRAW, x, ",", y, ";"); + break; + + case SGK_SETLW: + /* Set pen width. + */ + break; + default: + fprintf (stderr, "sgi2uhpp: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Terminate plotting and exit. + */ + fwrite (DEV_END, strlen(DEV_END), 1, out); + fprintf (out, "\n"); +} diff --git a/unix/gdev/sgidev/sgi2uhplj.c b/unix/gdev/sgidev/sgi2uhplj.c new file mode 100644 index 00000000..7c8956ce --- /dev/null +++ b/unix/gdev/sgidev/sgi2uhplj.c @@ -0,0 +1,223 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UHPLJ.C -- Read IRAF SGI rasterfile from standard input, translate into + * the Hewlett Packard Printer Command Language (HP Laserjet Series) and + * write to standard output. + * + * Warning + * The output of this is for 150 dpi. At this resolution it will take + * some 200 seconds to plot an simple "prow". + * + * Usage + * sgi2uhplj.e [-params] [sgi_] [| lpr -Phpraw] + * + * -l N left edge; x plot origin in device pixels def DEF_LEFT + * -b N bottom edge; y plot origin in device pixels def DEF_BOTTOM + * -w N width of plot, device pixels starting from l def DEF_WIDTH + * -h N height of plot, device pixels starting from b def DEF_HEIGHT + * + * Numeric values may be appended directly to their flags or separated by a + * space; the input file name and the switches may occur in any order. + */ + +#define OSOK 0 /* normal successful completion */ +#define NBITS_CHAR 8 /* number of bits in a char */ + +/* Device opcodes and parameters. The default edge and width parameters (DEF_) + * are given in HP pixels, at 150 dots/inch. The HP plots in portrait mode + * by default so RO must be set in GRAPHCAP. Thus the maximum page `width' is + * 11*150pixels, `height' is 8.5*150 pixels. + */ + +#define DEV_INIT "\033*t150R\033*r1A" /* Enter graph. */ +#define DEV_END "\033*rB\014" /* Exit graph. */ +#define DEV_VECT "\033*p%03dX\033*p%03dY"/* x,y cursor posn in dots */ +#define DEV_RAST "\033*b%03dW" /* transfer raster graphics */ + +#define DEF_LEFT 15 /* origin in device pixels in x */ +#define DEF_WIDTH 1216 /* width in x (150d/i, 8.5" paper) */ +#define DEF_BOTTOM 30 /* origin in device pixels in y */ +#define DEF_HEIGHT 1590 /* height in y (150d/i, 11" paper) */ + +#define SZ_VECT 14 /* total chars in cursor position command */ +#define SZ_RAST 7 /* total chars in transfer graphics command */ + +/* graphcap entry for uhplj and sgi_hplaserjet. one problem with current + * entry is that graph comes out slightly to the right of center on the page + * The printer used, "hpraw", is site dependent. + * + * uhplj|UNIX generic interface to Hewlett-Packard LaserJet II:\ + * :BF:WS:XO#0:YO#0:LO#2:LS#2:\ + * :DD=plnode!hpii,tmp$sgk,!{ sgidispatch sgi2uhpii $F \ + * -l$(XO) -b$(YO) -w$(PX) -h$(PY) $F | lpr -Phpraw; rm $F; }&:\ + * :tc=sgi_hplaserjet: + * + * sgi_hplaserjet|Hewlett Packard LaserJet Plus at 150 dpi:\ + * :kf=bin$x_sgikern.e:tn=sgikern:cw#.0125:ch#.0294:\ + * :ar#1.325:xs#.2032:ys#.2692:xr#1200:yr#1590:\ + * :XO#8:YO#0:XW#1200:YW#1590:PX#1216:PY#1590:LO#1:LS#0:\ + * :BI:MF#8:RO:NB#8: + */ + +int dev_left; +int dev_bottom; +int dev_width; +int dev_height; + +static void translate (FILE *in, FILE *out); +static char *xyencode (int x, int y); + + +/* MAIN -- Main entry point for SGI2UHPII. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + char *argp; + int argno; + + + infile = "stdin"; + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case 'l': + dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT); + break; + case 'b': + dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM); + break; + case 'w': + dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH); + break; + case 'h': + dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT); + break; + default: + break; + } + + } else { + /* Input sgi-raster file specification. + */ + infile = argp; + } + } + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2uhpii): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the rasterfile. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI Raster File format into Hewlett Packard + * Raster graphics instructions and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + int n1, swap_bytes; + int n, nlines, length, len_buf; + register unsigned char *bp1, *buffer1; + char buf_rast [SZ_RAST]; + + + swap_bytes = isSwapped (); + + len_buf = dev_width / NBITS_CHAR; + buffer1 = (unsigned char *)malloc (len_buf); + + /* Output device initialization. + */ + fwrite (xyencode (dev_left, dev_bottom), SZ_VECT, 1, out); + fwrite (DEV_INIT, strlen(DEV_INIT), 1, out); + + /* Process the raster file + */ + nlines = dev_height; + while ((n = fread (buffer1, len_buf, 1, in)) > 0) { + + if (swap_bytes) + bswap2 (buffer1, buffer1, len_buf); + + /* Keep track of number of lines left on the page. + */ + if (!(nlines--)) { + nlines += dev_height; + fwrite (DEV_END, strlen (DEV_END), 1, out); + fwrite (xyencode (dev_left, dev_bottom), SZ_VECT, 1, out); + fwrite (DEV_INIT, strlen (DEV_INIT), 1, out); + } + + /* Search for trailing null bytes to trim them off. + */ + length = len_buf; + for (bp1 = buffer1+length; length && *(--bp1) == 0; length--) + ; + + n1 = length; + if (n1 == 0) { + n1 = 1; + *buffer1 = 0; + } + + /* Now copy out this line and prefix it with the control codes. + */ + sprintf (buf_rast, DEV_RAST, n1); + fwrite (buf_rast, SZ_RAST, 1, out); + fwrite (buffer1, n1, 1, out); + } + + /* Terminate plotting and exit. + */ + fwrite (DEV_END, strlen(DEV_END), 1, out); +} + + +/* XYENCODE -- Encode x, y into a character string formatted for the device. + */ +static char * +xyencode (int x, int y) +{ + static char obuf [SZ_VECT]; + + memset (obuf, 0, SZ_VECT); + sprintf (obuf, DEV_VECT, x, y); + return (obuf); +} diff --git a/unix/gdev/sgidev/sgi2uimp.c b/unix/gdev/sgidev/sgi2uimp.c new file mode 100644 index 00000000..a8f566ed --- /dev/null +++ b/unix/gdev/sgidev/sgi2uimp.c @@ -0,0 +1,341 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UIMP.C -- Read IRAF SGI metacode from standard input, translate into + * the Impress language and write to standard output. + * + * Usage + * sgi2uimp.e [-params] [sgi_metacode] [| lpr -v -Pimagen] + * + * -l N left edge; x plot origin in device pixels def DEF_LEFT + * -b N bottom edge; y plot origin in device pixels def DEF_BOTTOM + * -w N width of plot, device pixels starting from l def DEF_WIDTH + * -h N height of plot, device pixels starting from b def DEF_HEIGHT + * -p O.S pen width `origin' and `slope' def DEF_PENBASE + * .DEF_PENSLOPE + * + * Numeric values may be appended directly to their flags or separated by a + * space; the input file name and the switches may occur in any order. + * The windowing parameters are specified explicitly rather than using the + * plotter resolution and paper size due to differences in exactly where + * each different Imagen begins and ends plotting within the paper window. + * + */ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define GKI_MAXNDC 32767 /* SGK units */ + +/* Device opcodes and parameters. The default edge and width parameters + * (DEF_), given in device pixels for a 240 dot/inch Imagen with 8 1/2" x 11" + * paper, should be modified to fit the local plotter. + */ +#define DEF_LEFT 85 /* origin in device pixels in x */ +#define DEF_WIDTH 2490 /* width in x (240d/i, 11" paper) */ +#define DEF_BOTTOM 50 /* origin in device pixels in y */ +#define DEF_HEIGHT 1905 /* height in y (240d/i, 8.5" paper)*/ +#define DEF_PENBASE 2 /* base pen width */ +#define DEF_PENSLOPE 2 /* pen slope (b.s=3.2 ==> 3,5,7,9) */ +#define SZ_PENPARAM 5 /* max chars in penwidth parameter */ +#define BLACK_LINE 15 /* draw solid line */ +#define CREATE_PATH 230 /* set up set of vertices */ +#define DRAW_PATH 234 /* draw that set of vertices */ +#define END_DOCUMENT 255 /* end of document */ +#define END_PAGE 219 /* formfeed */ +#define HV_VALUE 125 /* 0 11 11 101 (orig, axes, orient)*/ +#define SET_ABS_H 135 /* move absolute in h */ +#define SET_ABS_V 137 /* move absolute in v */ +#define SET_HV_SYSTEM 205 /* establish coordinate system */ +#define SET_PEN 232 /* set pen width */ +#define SZ_HEAD 3 /* # header opcode bytes in obuf */ +#define SZ_TAIL 2 /* # trailing opcode bytes in obuf */ +#define COUNT_OFFSET 1 /* byte offset to npoints in obuf */ + +/* Output macros -- watch out for SZ_OBUF; some Imagens have a limited amount + * of memory for the DRAW buffer: + */ +#define SZ_OBUF (1024) +#define DECL_OBUF register char *op; char *np; char obuf[SZ_OBUF+1]; +#define o_clear (op=obuf) +#define o_flush(o) fwrite(obuf,op-obuf,1,o) +#define putbyte(v) (*op++ = (v)) +#define putword(v) ((*op++ = (v)/256), (*op++ = (v)%256)) +#define setcount(b,v) ((np = obuf+b), (*np++ = (v)/256), (*np = (v)%256)) +#define npoints ((op-obuf - SZ_HEAD)/4) +#define obuf_full ((op-obuf + SZ_TAIL) >= SZ_OBUF) + +struct sgi_inst { + short opcode; + short x; + short y; +}; + +int imp_left; +int imp_bottom; +int imp_width; +int imp_height; +int imp_penbase = DEF_PENBASE; +int imp_penslope = DEF_PENSLOPE; + +static void translate (FILE *in, FILE *out); + + +/* MAIN -- Main entry point for SGI2UIMP. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + char *argp; + int argno; + int np; + char penparam[SZ_PENPARAM]; + + + infile = "stdin"; + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case 'l': + imp_left = get_iarg (argp[2], argv, argno, DEF_LEFT); + break; + case 'b': + imp_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM); + break; + case 'w': + imp_width = get_iarg (argp[2], argv, argno, DEF_WIDTH); + break; + case 'h': + imp_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT); + break; + case 'p': + if (argp[2] == (char) 0) + if (argv[argno+1] == NULL) { + fprintf (stderr, "missing arg to switch `%s';", + argp); + fprintf (stderr, " reset to %d.%d\n", imp_penbase, + imp_penslope); + } else + strcpy (penparam, argv[++argno]); + else + strcpy (penparam, argv[argno]+2); + + np = sscanf (penparam, "%d . %d", &imp_penbase, + &imp_penslope); + if (np == 1) { + imp_penslope = imp_penbase; + } else if (np < 1) { + imp_penbase = DEF_PENBASE; + imp_penslope = DEF_PENSLOPE; + } + + break; + default: + break; + } + + } else { + /* Input sgi-metacode file specification. + */ + infile = argp; + } + } + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2uimp): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the metacode. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into the device + * language and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + int n, x, y, swap_bytes; + float xscale, yscale; + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + DECL_OBUF; + + swap_bytes = isSwapped(); + + xscale = (float) imp_width / (float) GKI_MAXNDC; + yscale = (float) imp_height / (float) GKI_MAXNDC; + + /* Output device header instructions. + */ + fprintf (out, "@Document(%s, %s, %s, %s, %s, %s)", + "language impress", "pagecollation on", "jamresistance on", + "name \"IRAF SGI plot\"", "prerasterization on", "jobheader off"); + + /* Output page orientation and coordinate system initialization. + */ + putc (SET_HV_SYSTEM, out); + putc (HV_VALUE, out); + + /* Initialize pen width. + */ + putc (SET_PEN, out); + putc (1 * imp_penbase, out); + + o_clear; + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + /* Terminate and output any DRAW buffer contents. + */ + if (npoints > 1) { + setcount (COUNT_OFFSET, npoints); + putbyte (DRAW_PATH); + putbyte (BLACK_LINE); + o_flush (out); + } + + o_clear; + putbyte (END_PAGE); + putbyte (SET_ABS_H); + putword (0); + putbyte (SET_ABS_V); + putword (0); + o_flush (out); + break; + + case SGK_MOVE: + /* Terminate and output any DRAW buffer contents. + */ + if (npoints > 1) { + setcount (COUNT_OFFSET, npoints); + putbyte (DRAW_PATH); + putbyte (BLACK_LINE); + o_flush (out); + } + + x = imp_left + sgip->x * xscale; + y = imp_bottom + sgip->y * yscale; + + /* Initialize output buffer for start of draw instruction. + */ + o_clear; + putbyte (CREATE_PATH); + putword (1); + putword (x); putword (y); + + break; + + case SGK_DRAW: + x = imp_left + sgip->x * xscale; + y = imp_bottom + sgip->y * yscale; + putword (x); putword (y); + + /* If we are about to exceed output buffer, flush and re- + * initialize starting with current point. + */ + if (obuf_full) { + setcount (COUNT_OFFSET, npoints); + putbyte (DRAW_PATH); + putbyte (BLACK_LINE); + o_flush (out); + + /* Reinitialize DRAW buffer. + */ + o_clear; + putbyte (CREATE_PATH); + putword (1); + putword (x); putword (y); + } + + break; + + case SGK_SETLW: + /* Terminate and output any DRAW buffer contents. + */ + if (npoints > 1) { + setcount (COUNT_OFFSET, npoints); + putbyte (DRAW_PATH); + putbyte (BLACK_LINE); + o_flush (out); + o_clear; + } + + /* Set pen width. + */ + putc (SET_PEN, out); + putc ((imp_penbase + ((sgip->x) - 1) * imp_penslope), out); + break; + + default: + fprintf (stderr, "sgi2uimp: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Flush any remaining buffered points. + */ + if (npoints > 1) { + setcount (COUNT_OFFSET, npoints); + putbyte (DRAW_PATH); + putbyte (BLACK_LINE); + o_flush (out); + } + + /* Signal end of page and end of document. + */ + putc (END_PAGE, out); + putc (END_DOCUMENT, out); +} diff --git a/unix/gdev/sgidev/sgi2uptx.c b/unix/gdev/sgidev/sgi2uptx.c new file mode 100644 index 00000000..6c44f334 --- /dev/null +++ b/unix/gdev/sgidev/sgi2uptx.c @@ -0,0 +1,61 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define NBITS_CHAR 8 /* number of bits in a char */ +#define MASK 64 /* printronix raster flag */ +#define START_LINE "\005" /* start of raster line control code */ +#define END_LINE "\012" /* end of raster line control code */ +#define START_PAGE "\014" /* form feed */ + +/* PRINTRONIX translator from the SGI bitmap file to the STDOUT */ + +int +main (int argc, char *argv[]) +{ + + FILE *fpi; + char *buffer; + int n, len_buf, nlines; + int index; /* goes through all 8 files */ + int px, py; + + px = atoi (argv[1]); + py = atoi (argv[2]); + len_buf = px/NBITS_CHAR; + buffer = (char *) malloc (len_buf); + + for (index=3; index<argc; index++) { + + if (index != 3) fwrite (START_PAGE, 1, 1, stdout); + fpi = fopen (argv[index], "r"); + nlines = py; + + while (fread (buffer, len_buf, 1, fpi)) { + + /* Keep track of number of lines left on the page. */ + if (!(nlines--)) { + nlines += py; + fwrite (START_PAGE, 1, 1, stdout); + } + + /* Turn on the raster flag on every data byte */ + for (n = 0; n < len_buf; n++) buffer[n] |= MASK; + + /* Now copy out this line and bracket it with the control codes. */ + fwrite (START_LINE, 1, 1, stdout); + fwrite (buffer, len_buf, 1, stdout); + fwrite (END_LINE, 1, 1, stdout); + + } + + fclose (fpi); + + } + + return (0); +} diff --git a/unix/gdev/sgidev/sgi2uqms.c b/unix/gdev/sgidev/sgi2uqms.c new file mode 100644 index 00000000..e91d7e38 --- /dev/null +++ b/unix/gdev/sgidev/sgi2uqms.c @@ -0,0 +1,296 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UQMS.C -- Read IRAF SGI metacode from standard input, translate into + * the QMS Vector Graphics Mode (Talaris Lasergrafix, QUIC Command Mode) and + * write to standard output. + * + * Usage + * sgi2uqms.e [-params] [sgi_metacode] [| lpr -Pqms] + * + * -l N left edge; x plot origin in device pixels def DEF_LEFT + * -b N bottom edge; y plot origin in device pixels def DEF_BOTTOM + * -w N width of plot, device pixels starting from l def DEF_WIDTH + * -h N height of plot, device pixels starting from b def DEF_HEIGHT + * -p O.S pen width `origin' and `slope' def DEF_PENBASE + * .DEF_PENSLOPE + * + * Numeric values may be appended directly to their flags or separated by a + * space; the input file name and the switches may occur in any order. + */ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define GKI_MAXNDC 32767 /* SGK units */ + +/* Device opcodes and parameters. The default edge and width parameters (DEF_) + * are given in QMS pixels, at 300 dots/inch. The QMS y-origin is at the + * top of the page, so in GRAPHCAP, YF must be set, and Landscape Orientation + * used in the QMS. Thus the maximum page `width' is 11*300 pixels, `height' + * is 8.5*300 pixels. + */ +#define DEV_INIT "\012^PY^-\012^ISYNTAX00010^IOL^F^IGV" /* Enter graph.*/ +#define DEV_END "^IGE^ISYNTAX00000^IOP^O\012^PN^-\012" /* Exit graph. */ +#define DEV_FRAME "^," /* QMS Vector Graphics Mode form feed instr */ +#define DEV_MOVE "^U" /* QMS (VGM) pen-up instruction */ +#define DEV_DRAW "^D" /* QMS (VGM) pen-down instruction */ +#define DEV_SETLW "^PW" /* QMS (VGM) Set Line Width (follow w/ nn) */ + +#define DEF_LEFT 30 /* origin in device pixels in x */ +#define DEF_WIDTH 3180 /* width in x (300d/i, 11" paper) */ +#define DEF_BOTTOM 60 /* origin in device pixels in y */ +#define DEF_HEIGHT 2415 /* height in y (300d/i, 8.5" paper) */ +#define DEF_PENBASE 3 /* base pen width (LW 1->2) */ +#define DEF_PENSLOPE 4 /* pen width slope (LW 2->4, 3->6 etc.) */ +#define SZ_PENCMD 5 /* total no. of chars in penwidth instruction */ +#define SZ_PENVAL 2 /* no. of chars in penwidth value */ +#define SZ_VECT 11 /* total no. chars in a MOVE or DRAW inst. */ +#define SZ_COORD 4 /* no. of chars in device coordinate */ + +struct sgi_inst { + short opcode; + short x; + short y; +}; + +int dev_left; +int dev_bottom; +int dev_width; +int dev_height; +int dev_penbase = DEF_PENBASE; +int dev_penslope = DEF_PENSLOPE; + +static void translate (FILE *in, FILE *out); +static char *xyencode (int opcode, int x, int y); +static char *penencode (char *opcode, int val); + + + +/* MAIN -- Main entry point for SGI2UQMS. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + char *argp; + int argno; + int np; + char penparam[SZ_PENCMD]; + + + infile = "stdin"; + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case 'l': + dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT); + break; + case 'b': + dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM); + break; + case 'w': + dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH); + break; + case 'h': + dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT); + break; + case 'p': + if (argp[2] == (char) 0) + if (argv[argno+1] == NULL) { + fprintf (stderr, "missing arg to switch `%s';", + argp); + fprintf (stderr, " reset to %d.%d\n", dev_penbase, + dev_penslope); + } else + strcpy (penparam, argv[++argno]); + else + strcpy (penparam, argv[argno]+2); + + np = sscanf (penparam, "%d . %d", &dev_penbase, + &dev_penslope); + if (np == 1) { + dev_penslope = dev_penbase; + } else if (np < 1) { + dev_penbase = DEF_PENBASE; + dev_penslope = DEF_PENSLOPE; + } + + break; + default: + break; + } + + } else { + /* Input sgi-metacode file specification. + */ + infile = argp; + } + } + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2uqms): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the metacode. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into device + * instructions and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + int n, x, y, swap_bytes; + float xscale, yscale; + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + + + swap_bytes = isSwapped(); + + xscale = (float) dev_width / (float) GKI_MAXNDC; + yscale = (float) dev_height / (float) GKI_MAXNDC; + + /* Output device initialization. + */ + fwrite (DEV_INIT, strlen(DEV_INIT), 1, out); + + /* Initialize pen width. + */ + fwrite (penencode (DEV_SETLW, dev_penbase), SZ_PENCMD, 1, out); + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + fwrite (DEV_FRAME, strlen(DEV_FRAME), 1, out); + break; + + case SGK_MOVE: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + fwrite (xyencode ('U', x, y), SZ_VECT, 1, out); + break; + + case SGK_DRAW: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + fwrite (xyencode ('D', x, y), SZ_VECT, 1, out); + break; + + case SGK_SETLW: + /* Set pen width. + */ + fwrite (penencode (DEV_SETLW, dev_penbase + + ((sgip->x) - 1) * dev_penslope), SZ_PENCMD, 1, out); + break; + + default: + fprintf (stderr, "sgi2uqms: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Terminate plotting and exit. + */ + fwrite (DEV_END, strlen(DEV_END), 1, out); +} + + +/* XYENCODE -- Encode x, y into a character string formatted for the device. + */ +static char * +xyencode ( + int opcode, /* draw or move */ + int x, /* must be positive */ + int y /* must be positive */ +) +{ + static char obuf[] = "^X0000:0000"; + register int digit, n; + register char *op; + int i; + + obuf[1] = opcode; + i = SZ_VECT - 1 - SZ_COORD - 1; + for (op = &obuf[i], digit = SZ_COORD, n=x; --digit >= 0; n = n / 10) + *op-- = n % 10 + '0'; + i = SZ_VECT - 1; + for (op = &obuf[i], digit = SZ_COORD, n=y; --digit >= 0; n = n / 10) + *op-- = n % 10 + '0'; + + return (obuf); +} + + +/* PENENCODE -- Encode base, slope into a character string formatted for the + * device set-pen command. + */ +static char * +penencode ( + char *opcode, /* device set-linewidth command */ + int val /* device line width */ +) +{ + static char obuf[SZ_PENCMD+1]; + register int digit, n; + register char *op; + + strcpy (obuf, opcode); + for (op = &obuf[SZ_PENCMD-1], digit = SZ_PENVAL, n=val; --digit >= 0; + n = n / 10) + *op-- = n % 10 + '0'; + + return (obuf); +} diff --git a/unix/gdev/sgidev/sgi2xbm.c b/unix/gdev/sgidev/sgi2xbm.c new file mode 100644 index 00000000..6d4c230a --- /dev/null +++ b/unix/gdev/sgidev/sgi2xbm.c @@ -0,0 +1,135 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "sgiUtil.h" + + +/* SGI2XBM.C -- Read an IRAF SGI bitmap file on standard input and convert + * to a GIF format image on standard outout. + * + * Usage: + * sgi2xbm.e [-w N] [-h NY] [-i] [ [sgi_bitmap] [sgi_bitmap] ... ] + * + * -w N width of input bitmap and output image + * -h N height of input bitmap and output image + * -i invert the bitmap values before conversion + * + * The input file name and the switches may occur in any order. The bitmap + * may be inverted here using the -i flag. + * + * Sample graphcaps for this translator might look like: + * + * g-xbm|UNIX generic interface to multi-frame XBM file generator:\ + * :DD=ugif,tmp$sgk,!{ sgidispatch sgi2xbm -w $(PX) -h $(PY) \ + * $F.[1-8] > sgixbm$$; rm $F.[1-8]; }&:\ + * :MF#8:NF:tc=sgi_image_format: + * + * sgi_image_format|Generic raster file format specification:\ + * :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\ + * :xr#640:yr#480:PX#640:PY#480:XW#640:YW#480:\ + * :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0: + * + * All bitmaps will be dumped to the file 'sgixbmXXX' in the local directory + * where XXX is a pid. + * + * To change the image size the graphcap :xr, :PX, :XW (X-dimension) and + * :yr, :PY, :XY (Y-dimension) fields all need to be changed. The -i + * flag must be specified in the graphcap DD string. + * + */ + +#define NBITS_CHAR 8 /* number of bits in a char */ +#define DEF_WIDTH 640 /* default image width */ +#define DEF_HEIGHT 480 /* default image height */ +#define MAX_INFILES 16 /* max number of input bitmaps */ +#define SZ_FNAME 64 /* size of a filename */ + +typedef unsigned char byte; + +static int px = DEF_WIDTH; +static int py = DEF_HEIGHT; +static int invert = 0; +static char *infile[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + +int +main (int argc, char *argv[]) +{ + FILE *fd; + byte *buffer; + int i, n, len_buf, numin = 0, cnt = 0; + int index; /* goes through all files */ + + + /* Process the command line. + */ + for (i=1; i < argc; i++) { + if (argv[i][0] == '-') { + if (strcmp (argv[i], "-w") == 0) + px = atoi (argv[++i]); + else if (strcmp (argv[i], "-h") == 0) + py = atoi (argv[++i]); + else if (strcmp (argv[i], "-i") == 0) + invert++; + } else { + /* input sgi-bitmap file specification */ + if (numin < MAX_INFILES) + infile[numin++] = argv[i]; + } + + } + + /* Allocate some space for the working buffer. */ + len_buf = px / NBITS_CHAR; + buffer = (byte *) malloc (len_buf); + + /* Loop over the input bitmaps, writing the converted output to + * the stdout. + */ + for (index = 0; index == 0 || index < numin; index++) { + + /* Open the input file. */ + fd = (infile[index] ? fopen (infile[index], "r") : stdin); + + if (index > 0) printf ("\n"); + + printf ("#define xbm%03d_width %d\n", index, px); + printf ("#define xbm%03d_height %d\n", index, py); + printf ("static char xbm%03d_bits[] = {\n ", index); + + n = 0; + cnt = 0; + while (fread (buffer, len_buf, 1, fd)) { + /* If we're on a MSB ordered machine wordswap the bitmap so + * it's in the correct order for unpacking to be interpreted + * as an LSB-ordered image. + */ + if (!isSwapped ()) + bswap4 (buffer, buffer, len_buf); + + /* Write out the pixels. */ + for (i=0; i < len_buf; i++, cnt++) { + printf ("0x%.2x", + (byte) (invert ? ~buffer[i]: buffer[i])), n += 4; + if (cnt < (len_buf * py - 1)) + printf (","), n++; + else + printf ("};\n"); + if (n > 70) + printf ("\n "), n=0; + } + } + + if (fd != stdin) + fclose (fd); + fflush (fd); + } + free (buffer); + + return (0); +} diff --git a/unix/gdev/sgidev/sgiUtil.c b/unix/gdev/sgidev/sgiUtil.c new file mode 100644 index 00000000..25214450 --- /dev/null +++ b/unix/gdev/sgidev/sgiUtil.c @@ -0,0 +1,132 @@ +/** + * SGIUTIL.C -- Shared utility procedures for the SGI translators. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> + +#define import_spp +#define import_error +#include <iraf.h> + + +/** + * BSWAP2 -- Move bytes from array "a" to array "b", swapping successive + * pairs of bytes. The two arrays may be the same but may not be offset + * and overlapping. + */ +void +bswap2 ( + unsigned char *a, /* input array */ + unsigned char *b, /* output array */ + int nbytes /* number of bytes to swap */ +) +{ + register unsigned char *ip, *op, *otop; + register unsigned int temp; + + ip = a; + op = b; + otop = op + (nbytes & ~1); + + /* Swap successive pairs of bytes. + */ + while (op < otop) { + temp = *ip++; + *op++ = *ip++; + *op++ = temp; + } + + /* If there is an odd byte left, move it to the output array. + */ + if (nbytes & 1) + *op = *ip; +} + + +/* BSWAP4 - Move bytes from array "a" to array "b", swapping the four bytes + * in each successive 4 byte group, i.e., 12345678 becomes 43218765. + * The input and output arrays may be the same but may not partially overlap. +*/ +void +bswap4 ( + unsigned char *a, /* input array */ + unsigned char *b, /* output array */ + int nbytes /* number of bytes to swap */ +) +{ + register int n; + register unsigned char *ip, *op, *tp; + static unsigned char temp[4]; + + tp = temp; + ip = (unsigned char *)a; + op = (unsigned char *)b; + + /* Swap successive four byte groups. + */ + for (n = nbytes >> 2; --n >= 0; ) { + *tp++ = *ip++; + *tp++ = *ip++; + *tp++ = *ip++; + *tp++ = *ip++; + *op++ = *--tp; + *op++ = *--tp; + *op++ = *--tp; + *op++ = *--tp; + } + + /* If there are any odd bytes left, move them to the output array. + * Do not bother to swap as it is unclear how to swap a partial + * group, and really incorrect if the data is not modulus 4. + */ + for (n = nbytes & 03; --n >= 0; ) + *op++ = *ip++; +} + + +/** + * ISSWAPPED -- Test whether we are running on a byte-swapped machine. + */ +int +isSwapped (void) +{ + union { + short tswap; + char b[2]; + } test; + + test.tswap = 1; + return ((int) test.b[0]); +} + + +/** + * GET_IARG -- Get an integer argument, whether appended directly to flag + * or separated by a whitespace character; if error, report and assign + * default. + */ +int +get_iarg ( + char argp, + char **argv, + int argno, + int def_val +) +{ + int temp_val; + + if (argp == (char) 0) { + if (argv[argno+1] == NULL) { + fprintf (stderr, "missing arg to switch `%c';", argp); + fprintf (stderr, " reset to %d\n", def_val); + temp_val = def_val; + } else + temp_val = atoi (argv[++argno]); + } else + temp_val = atoi (argv[argno]+2); + + return (temp_val); +} diff --git a/unix/gdev/sgidev/sgiUtil.h b/unix/gdev/sgidev/sgiUtil.h new file mode 100644 index 00000000..9630a03e --- /dev/null +++ b/unix/gdev/sgidev/sgiUtil.h @@ -0,0 +1,10 @@ +/** + * SGIUTIL.H -- Declarations for the SGI utility routines. + */ + +void bswap2 (unsigned char *a, unsigned char *b, int nbytes); +void bswap4 (unsigned char *a, unsigned char *b, int nbytes); + +int isSwapped (void); + +int get_iarg (char argp, char **argv, int argno, int def_val); diff --git a/unix/gdev/sgidev/sgidispatch.c b/unix/gdev/sgidev/sgidispatch.c new file mode 100644 index 00000000..90201460 --- /dev/null +++ b/unix/gdev/sgidev/sgidispatch.c @@ -0,0 +1,70 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define import_spp +#define import_error +#define import_kernel +#define import_knames +#include <iraf.h> + + +/* + * SGIDISPATCH.C -- Determine pathname to the executable for the named SGI + * translator, and execute the translator. Pass all command line arguments + * to the child, which also inherits stdin, stdout, and stderr. + * + * Usage: sgidispatch translator [args] + */ + +#define DEF_HOST "unix" /* default host system */ +#define F_OK 0 /* access mode `file exists' */ +#ifndef X_OK +#define X_OK 1 /* access mode `executable' */ +#endif + +char *irafpath(); + + +/* MAIN -- Main entry point for SGIDISPATCH. + */ +int +main (int argc, char *argv[]) +{ + char tpath[SZ_PATHNAME+1]; + char translator[SZ_PATHNAME+1]; + int ip; + + /* Do nothing if called with no arguments. + */ + if (argc < 2) + exit (OSOK); + + /* Construct pathname to translator. + */ + strcpy (translator, argv[1]); + ip = strlen (translator); + if (strcmp (&translator[ip], ".e") != 0) + strcat (translator, ".e"); + sprintf (tpath, "%s", irafpath(translator)); + + if (access (tpath, X_OK) == ERR) { + fprintf (stderr, "Fatal (sgidispatch): unable to access SGI"); + fprintf (stderr, " translator `%s'\n", tpath); + fflush (stderr); + exit (OSOK+1); + } + + /* Set up i/o for translator and attempt to fork. + */ + argv[argc] = 0; + execv (tpath, &argv[1]); + fprintf (stderr, "Fatal (sgidispatch): unable to execv(%s, ...)\n", + tpath); + fflush (stderr); + exit (OSOK+1); +} |