Search:

Return to previous page

Contents of file 'epsimg/epsimg.w':



    1   % File:        epsimg.w [CWEB source code]
    2   % Last change: February 21, 2004
    3   % Author:      Fredrik Jonsson
    4   % Description: CWEB source code for the EPSIMG program. Given a matrix of
    5   %              numerical values stored in a regular ASCII text file, the
    6   %              EPSIMG program creates a grey-scale Encapsulated PostScript
    7   %              image of the matrix using its elements as specification of
    8   %              the brightness of the corresponding pixels in the image.
    9   %              For information on the CWEB programming language, see
   10   %              http://www.literateprogramming.com.
   11   % Compilation: Compile this program by using the enclosed Makefile, or use
   12   %              the blocks of the Makefile as listed in section five of the
   13   %              documentation (file epsimg.ps or epsimg.pdf). The C source
   14   %              code (as generated from this CWEB code) conforms to the ANSI
   15   %              standard for the C programming language (which is equivalent
   16   %              to the ISO C89 standard for C).
   17   %
   18   % Copyright (C) 2004, Fredrik Jonsson
   19   %
   20   \def\version{1.6}
   21   \def\lastrevdate{February 21, 2004}
   22   \input epsf
   23   \font\eightcmr=cmr8
   24   \font\tensc=cmcsc10
   25   \font\eightcmssq=cmssq8
   26   \font\eightcmssqi=cmssqi8
   27   \font\twentycmcsc=cmcsc10 at 20 truept
   28   \def\epsimg{{\eightcmr EPSIMG\spacefactor1000}}
   29   \def\CEE{{\eightcmr C\spacefactor1000}}     % The C programming language
   30   \def\CWEB{{\eightcmr CWEB\spacefactor1000}} % The CWEB programming language
   31   \def\MATLAB{{\eightcmr MATLAB\spacefactor1000}} % The MATLAB ditto
   32   \def\endalg{\vrule height 1.4ex width .6ex depth .4ex} % Rectangular bullet
   33   %
   34   % Define a handy macro for listing the steps of an algorithm.
   35   %
   36   \newdimen\aitemindent \aitemindent=26pt
   37   \newdimen\aitemleftskip \aitemleftskip=36pt
   38   \def\aitem[#1]{\smallbreak\noindent\hbox to 10pt{}%
   39     \hbox to\aitemindent{\bf #1\hfill}%
   40     \hangindent\aitemleftskip\ignorespaces}
   41   %
   42   % Define a handy macro for the list of program revisions.
   43   %
   44   \newdimen\citemindent \citemindent=80pt
   45   \newdimen\citemleftskip \citemleftskip=90pt
   46   \def\citem[#1]{\smallbreak\noindent\hbox to 10pt{}%
   47     \hbox to\citemindent{\bf #1\hfill}%
   48     \hangindent\citemleftskip\ignorespaces}
   49   %
   50   % Define a handy macro for listing of operator descriptions.
   51   %
   52   \newdimen\oitemindent \oitemindent=66pt
   53   \newdimen\oitemleftskip \oitemleftskip=76pt
   54   \def\oitem[#1]{\smallbreak\noindent\hbox to 10pt{}%
   55     \hbox to\oitemindent{\bf #1\hfill}%
   56     \hangindent\oitemleftskip\ignorespaces}
   57   
   58   \datethis
   59   
   60   @*Introduction.
   61   \vskip 120pt
   62   \centerline{\twentycmcsc Epsimg}
   63   \vskip 20pt
   64   \centerline{Creates grey-scale Encapsulated PostScript images of matrices
   65     of numerical data}
   66   \vskip 2pt
   67   \centerline{(Version \version\ of \lastrevdate)}
   68   \vskip 10pt
   69   \centerline{Written by Fredrik Jonsson}
   70   \vskip 80pt
   71   \noindent
   72   Given a matrix of floating-point numbers stored in a regular ASCII text file,
   73   this \CWEB\footnote{${}^\dagger$}{For information on the \CWEB\ programming
   74   language by Donald E.~Knuth, as well as samples of \CWEB\ programs, see
   75   {\tt http://www-cs-faculty.stanford.edu/\~\ \kern -5pt knuth/cweb.html}.
   76   For general information on literate programming, see
   77   {\tt http://www.literateprogramming.com}.} program creates a grey-scale
   78   Encapsulated PostScript (EPS) image of the matrix using its elements as
   79   specification of the brightness of the corresponding pixels in the image.
   80   
   81   I do by no means claim to have written a program that generates fully optimized
   82   Encapsulated PostScript. The output images are in many cases large, and can
   83   in many cases be considerably reduced in size, in particular for binary or
   84   few-level grayscale images, for which run-length encoding easily can be
   85   applied. (In run-length encoding a long row of
   86   identical pixels is parametrized as a loop, without the need of individual
   87   specification of each pixel.) However, for my purposes it works fine, since
   88   I often only is concerned with the evaluation of gray-scale images, generated
   89   by mathematical means and often with no a priori specification of the number
   90   of intensity levels.
   91   
   92   Of course, there are other ways of generating Encapsulated PostScript images
   93   of sampled of simulated data, as for example using the {\tt image()} function
   94   of \MATLAB. An advantage with using a stand-alone program, however, is that
   95   it is easily incorporated in scripts for batch processing. In addition, the
   96   \epsimg\ program is provided free of charge.
   97   \bigskip
   98   \noindent Copyright \copyright\ Fredrik Jonsson, 2004.
   99   All rights reserved.
  100   \vfill
  101   
  102   @*Revision history of the program.
  103   \medskip
  104   
  105   \citem[2004-01-26]{[v.1.0]} {\tt <jonsson@@uni-wuppertal.de>}\hfill\break
  106   First properly working version of the \epsimg\ program. I have now for a
  107   longer time had in my mind that it would be useful to write a stand-alone
  108   program that is capable of generating Encapsulated PostScript images of
  109   data matrices, in similar to the {\tt image()} built-in function of \MATLAB.
  110   In particular, I have lately encountered some problems involving the optical
  111   analysis of diffraction patterns, and in order to visualize my generated data
  112   (without having to use \MATLAB\ every time) I this evening started the coding
  113   in \CWEB.
  114   
  115   \citem[2004-01-27]{[v.1.1]} {\tt <jonsson@@uni-wuppertal.de>}\hfill\break
  116   Continued with cleaning up the code and adding some features, such as the
  117   possibility of letting the program add a frame outlining the bounding box
  118   of the Encapsulated PostScript image, and a scaling of the $x$- or $y$-axis
  119   to leave the aspect ratio of the square pixels invariant even for non-square
  120   input matrices. Also changed the precision of the coordinates and gray scale
  121   specifications in order to get really smooth images. However, there still seem
  122   to remain some bug that causes the program to refuse to accept data files
  123   containing lines with trailing blank spaces and additional line feeds.
  124   [Coding finished at 00:45, 2004-01-28]
  125   
  126   \citem[2004-01-28]{[v.1.2]} {\tt <jonsson@@uni-wuppertal.de>}\hfill\break
  127   This morning fixed the remaining bug from yesterday, and wrote a basic example
  128   ({\tt example1}) as a block in the {\tt Makefile}, using AWK to generate a
  129   simple interference pattern that is visualized with the help of the \epsimg\
  130   program. Also wrote blocks that provide a proper rescaling of the image
  131   width or height whenever either the width or height is larger than their
  132   respective maximum values. Wrote an example ({\tt example2}) in the
  133   {\tt Makefile} that illustrates this automatic rescaling of the image.
  134   
  135   \citem[2004-01-30]{[v.1.3]} {\tt <jonsson@@uni-wuppertal.de>}\hfill\break
  136   This evening (time is now 01:55 Saturday morning) I started to sketch on
  137   a partitioning scheme for the reduction of data neccessary to save to disk.
  138   For many of my diffraction images, there are large areas that are of equal
  139   shade, and since they have considerable extent in the $x$- as well as
  140   $y$-direction, a run-length encoding (of the type used in the ancient program
  141   for generation of fractals that I wrote together with Tommy Ekola in 1996)
  142   of the Encapsulated PostScript will not fix the problem to any greater extent.
  143   Therefore, I started formulating a recursive scheme for the partitioning of
  144   data into smaller and smaller sub-blocks of the user-supplied matrix, which
  145   I for the sake of simplicity so far have assumed to be square, of size
  146   $[2^M\times 2^M]$ for some integer $M$.
  147   Wrote a MetaPost figure {\tt matfig.mp} that illustrates the partition scheme.
  148   
  149   \citem[2004-02-07]{[v.1.4]} {\tt <jonsson@@uni-wuppertal.de>}\hfill\break
  150   [Athens, Greece] Noticed that when viewed using Ghostview, the figures could
  151   not be zoomed properly. This was corrected by letting the program explicitly
  152   state {\tt \%\%!PS-Adobe-2.0 EPSF-1.2}, and by also explicitly stating the
  153   number of pages (that is to say, one) of the figure in the Encapsulated
  154   PostScript preamble, using {\tt \%\%Pages: 1}.
  155   
  156   \citem[2004-02-20]{[v.1.5]} {\tt <jonsson@@uni-wuppertal.de>}\hfill\break
  157   [\"Ostergarn, Gotland] Added the command-line options
  158   {\tt --commmented\_postscript} and {\tt --uncommmented\_postscript},
  159   explicitly forcing the program either to include comments on PostScript
  160   routines directly into the generated code (default),
  161   or forcing the program to suppress these comments (giving a slightly reduced
  162   size on disk).
  163   
  164   \citem[2004-02-21]{[v.1.6]} {\tt <jonsson@@uni-wuppertal.de>}\hfill\break
  165   [\"Ostergarn, Gotland] Wrote the final blocks of a major revision of the
  166   program, concerning the algorithm for generation of individual pixels.
  167   While the program previously explicitly stated the pixel boundaries as paths,
  168   I have now replaced this by a PostScript routine {\tt drawpixel} that takes
  169   a pixel bounding box given by the lower left and upper right corners
  170   $(\langle|llx|\rangle,\langle|lly|\rangle)$ and
  171   $(\langle|urx|\rangle,\langle|ury|\rangle)$ and draws and fills the pixel
  172   with a specified gray value.
  173   The syntax for this PostScript routine is (in the PostScript language)
  174   simply {\tt drawpixel} $\langle|llx|\rangle$ $\langle|lly|\rangle$
  175   $\langle|urx|\rangle$ $\langle|ury|\rangle$ $\langle|w|\rangle$, where
  176   $\langle|w|\rangle\in[0,1]$ is the whiteness of the actual pixel.
  177   I did, however, keep the possibility of generating the previous, more extensive
  178   form of PostScript, and in order to be able to switch the program into
  179   either mode, the options {\tt --compactified\_pixelcode} and
  180   {\tt --extensive\_pixelcode} were added as parts of the startup syntax.
  181   When applied to the previously written example with a $64\times64$-sized
  182   matrix of real numbers, the size of the generated was radically reduced
  183   from 590.3 kB to 152.4 kB, hence corresponding to a reduction by 74\%!
  184   However, there still remain to optimize the code, especially to write
  185   PostScript routines that takes the image matrix and automatically loops
  186   over the indices, instead of the current approach, where the bounding box
  187   of each individual pixel still is specified in the code. (The image generated
  188   by the {\tt image()} routine of \MATLAB\ is still considerably smaller in
  189   size than what the now optimized algorithm provides; so far the generated
  190   PostScript takes approximately 37 byte per pixel, which is far too much
  191   even for ``educational purpose''.)
  192   What remains now is to also include the more clever partitioning of the
  193   image for cases with many adjacent pixels of identical gray value.
  194   \medskip
  195   \centerline{\epsfxsize=40.0mm\epsfbox{examples/example1-compact.eps}}
  196   \medskip\nobreak
  197   \centerline{Figure R1. The example $64\times64$ image used in evaluating
  198   size reduction 2004-02-21.}
  199   
  200   @*Compiling the source code. The program is written in \CWEB, generating
  201   ANSI-C conforming source code and documentation as \TeX-source, and is to
  202   be compiled using the enclosed Makefile, leaving an executable
  203   file {\tt epsimg}\footnote{$\dagger$}{On platforms running Windows NT,
  204   Windows 2000, or any other operating system by Microsoft, the executable
  205   file will instead automatically be called {\tt epsimg.exe}.} and a
  206   PostScript file {\tt epsimg.ps} (the document you currently are reading),
  207   which contains the full documentation of the program:
  208   \bigskip
  209   {\obeyspaces\obeylines\tt
  210   ~   \#
  211   ~   \# Makefile designed for use with ctangle, cweave, gcc, and plain TeX.
  212   ~   \#
  213   ~   \# Copyright (C) 2004, Fredrik Jonsson <jonsson@@uni-wuppertal.de>
  214   ~   \#
  215   ~   CTANGLE  = ctangle
  216   ~   CC       = gcc
  217   ~   CCOPTS   = -O2 -Wall -ansi -pedantic \# follow ISO C89 (ANSI) strictly
  218   ~   LNOPTS   = -lm
  219   ~   CWEAVE   = cweave
  220   ~   TEX      = tex
  221   ~   DVIPS    = dvips
  222   ~   DVIPSOPT = -ta4 -D1200
  223   ~   ~
  224   ~   all: epsimg.exe epsimg.ps
  225   ~   ~
  226   ~   epsimg.exe: epsimg.o \# generate the executable file
  227   ~           \$(CC) \$(CCOPTS) -o epsimg epsimg.o \$(LNOPTS)
  228   ~   ~
  229   ~   epsimg.o: epsimg.c \# generate the object file
  230   ~           \$(CC) \$(CCOPTS) -c epsimg.c
  231   ~   ~
  232   ~   epsimg.c: epsimg.w \# generate C code from the CWEB source
  233   ~           \$(CTANGLE) epsimg
  234   ~   ~
  235   ~   epsimg.ps: epsimg.dvi \# generate the PostScript documentation
  236   ~           \$(DVIPS) \$(DVIPSOPT) epsimg.dvi -o epsimg.ps
  237   ~   ~
  238   ~   epsimg.dvi: epsimg.tex \# generate the device-independent documentation
  239   ~           \$(TEX) epsimg.tex
  240   ~   ~
  241   ~   epsimg.tex: epsimg.w \# generate plain TeX code from the CWEB source
  242   ~           \$(CWEAVE) epsimg
  243   ~   ~
  244   ~   clean:
  245   ~   ~       -rm -Rf *.c *.o *.exe *.aux *.log *.toc *.idx *.scn *.tex *.dvi}
  246   \bigskip
  247   
  248   @*Running the program. The program is entirely controlled by the command
  249   line options supplied when invoking the program, and the syntax is simply:
  250   \medskip
  251   {\obeyspaces\obeylines\tt
  252   ~   epsimg -i <infile> -o <outfile>
  253   }
  254   \medskip
  255   \noindent
  256   where {\tt <infile>} is a regular text file containing the matrix of numerical
  257   data, and {\tt <outfile>} is the name of the Encapsulated PostScript image
  258   that is to be generated.
  259   Instead of {\tt -i} and {\tt -o}, the switches can equivalently be specified
  260   in their longer forms {\tt --inputfile} and {\tt --outputfile}, respectively.
  261   
  262   Several options may additionally be specified; to see a listing of all
  263   available options, simply invoke \epsimg\ with the help switch {\tt -h}
  264   (or, equivalently, {\tt --help} in a longer form), as
  265   \medskip
  266   {\obeyspaces\obeylines\tt
  267   ~   epsimg -h
  268   }
  269   \medskip
  270   \noindent
  271   
  272   
  273   @*Compressing the size of the generated Encapsulated Postscript.
  274   In a general sense, the input to the \epsimg\ program is just an arbitrary
  275   matrix of numbers, with no a priori assumption on their individual values
  276   or their ordering.
  277   In many images, however, there are large areas of equal colour (or brightness,
  278   if we stick to the fact that the \epsimg\ program primarily is designed for
  279   the visualization of gray scale images), and instead of sequentially writing
  280   a large list of identical squares, of the same shading but slightly displaced
  281   with respect to one another, one may start thinking that there must be a more
  282   efficient method of saving the image to file.
  283   
  284   One possibility is to check the structure sequentially in the order the squares
  285   are written, and in case many boxes of the same shade appear, say in the
  286   row direction of the supplied matrix, a rectangle with this shade and with
  287   a length corresponding to the number of equal squares is to be drawn instead.
  288   This, however, may be an inefficient method as well, since any directionality
  289   in the image in the column direction of the matrix will be left unnoticed.
  290   In addition, if there are large fields of equal shade, a lot of neighbouring
  291   rows should be possible to further reduce, for example by instead drawing
  292   general rectangles which no longer need to be of the same height as the
  293   basic pixels.
  294   
  295   The question therefore arises: Would it not be possible to make a relatively
  296   simple divide-and-conquer description of the matrix, partitioning the matrix
  297   into rectangular building blocks of equal shade?
  298   In Fig.~1, on possibility of a partitioning scheme for the reduction of the
  299   data needed to save to disk is illustrated.
  300   \bigskip
  301   \centerline{\epsfxsize=107.55mm\epsfbox{matfig/matfig.1}}\medskip\nobreak
  302   \centerline{Figure 1. A possible partitioning scheme for square matrices
  303   of size $[2^M\times 2^M]$.}
  304   
  305   
  306   @*The main program. Here follows the general outline of the main program.
  307   
  308   For the flags that are internally used, for the settings of desired program
  309   actions, the significance of the flags are:
  310   |COMPACTIFIED_PIXELCODE| If set to a positive nonzero integer value,
  311   this flag causes the program to generate a
  312   compactified PostScript code for the definitions of the individual boxes
  313   of the image, i.e. the individual pixels.
  314   
  315   In order to have one single and generic output stream, the |OUTSTREAM|
  316   definition provides an easy solution to switching the output from file
  317   to terminal output, depending on which options that are detected at the
  318   command line during startup of the program.
  319   
  320   @c
  321   #include <math.h>
  322   #include <stdio.h>
  323   #include <stddef.h>
  324   #include <stdlib.h>
  325   #include <string.h>
  326   #include <time.h> /* to get automatically generated timestamp in EPS header */
  327   #include <ctype.h> /* to access |isalnum()| */
  328   
  329   #define VERSION_NUMBER "1.6"
  330   
  331   #define A4_PAGE_WIDTH (594)  /* A4 page width in pt (1/72 in) */
  332   #define A4_PAGE_HEIGHT (841) /* A4 page height in pt (1/72 in) */
  333   #define MAXIMUM_IMAGE_WIDTH (A4_PAGE_WIDTH-144) /* 1.0 inch default margin */
  334   #define MAXIMUM_IMAGE_HEIGHT (A4_PAGE_HEIGHT-144) /* 1.0 inch default margin */
  335   #define DEFAULT_IMAGE_WIDTH (0.8*MAXIMUM_IMAGE_WIDTH)
  336   #define DEFAULT_IMAGE_XCENTER (A4_PAGE_WIDTH/2)
  337   #define DEFAULT_IMAGE_YCENTER (A4_PAGE_HEIGHT/2)
  338   #define DEFAULT_LINETHICKNESS 1 /* default line thickness in pt (1/72 in) */
  339   
  340   #define OUTSTREAM (outfile_specified?fpout:stdout)
  341   #define SUCCESS 0 /* Return code for successful program termination */
  342   #define FAILURE 1 /* Return code for program termination caused by failure */
  343   
  344   #define COMPACTIFIED_PIXELCODE 1
  345   #define EXTENSIVE_PIXELCODE 2
  346   
  347   @<Global variables@>@;
  348   @<Subroutines@>@;
  349   
  350   int main(int argc, char *argv[])
  351   {
  352      @<Local variables@>@;
  353      @<Parse command line@>@;
  354      @<Open files@>@;
  355      @<Load text file into image matrix@>@;
  356      @<Normalize image matrix@>@;
  357      @<Initialize parameters of Encapsulated PostScript image@>@;
  358      @<Write preamble of Encapsulated PostScript image@>@;
  359      @<Write body of Encapsulated PostScript image@>@;
  360      @<Write closing of Encapsulated PostScript image@>@;
  361      @<Deallocate image matrix@>@;
  362      @<Close files@>@;
  363      return(SUCCESS);
  364   }
  365   
  366   @*Declaration of global variables. The only global variables allowed in
  367   my programs are |optarg|, which is the string of characters that specified
  368   the call from the command line, and |progname|, which simply is the string
  369   containing the name of the program, as it was invoked from the command line.
  370   
  371   @<Glob...@>=
  372      extern char *optarg; /* command line string */
  373      char *progname; /* name of the program as invoked from command line */
  374   
  375   @*Declarations of subroutines used by the program.
  376   
  377   @<Subroutines@>=
  378      @<Display help message@>@;
  379      @<Routine for allocation of double vectors@>@;
  380      @<Routine for allocation of double matrices@>@;
  381      @<Routine for deallocation of double vectors@>@;
  382      @<Routine for deallocation of double matrices@>@;
  383      @<Routine for loading matrix data from text file@>@;
  384      @<Routine for unloading matrix data previously loaded from text file@>@;
  385   
  386   @ Routine for displaying a help message at the screen.
  387   
  388   @<Display help message@>=
  389   void showsomehelp(void) {
  390     fprintf(stderr,"Usage: %s -i infile [options] [-o outfile]\n",progname);
  391     fprintf(stderr,"Options:\n");
  392     fprintf(stderr,
  393      "  -i, --inputfile <str>   Specifies the file where to find the intensity\n"
  394      "                          response for the actual property.\n");
  395     fprintf(stderr,
  396      "  -o, --outputfile <str>  Specifies the file where to save the trans-\n"
  397      "                          mitted optical pulse shape. Whenever this\n");
  398     fprintf(stderr,
  399      "                          option is not present at the command line,\n"
  400      "                          the generated time series will be written\n"
  401      "                          to standard terminal output instead, in\n"
  402      "                          which case any set verbose mode will be turned\n"
  403      "                          off (see -v option).\n");
  404     fprintf(stderr,
  405      "  -s, --sequential        Toggle sequential mode. Default: off.\n"
  406      "                          When generating the Encapsulated PostScript,\n"
  407      "                          in sequential mode, the data\n");
  408     fprintf(stderr,
  409      "                          is scanned column/row-wise, with an individual\n"
  410      "                          pixel written for each data point of the input\n"
  411      "                          matrix. In this mode the program will ignore\n"
  412      "                          any possibilities of reducing the data through\n"
  413      "                          a more efficient partitioning of the input\n"
  414      "                          matrix.\n");
  415     fprintf(stderr,
  416      "  -v, --verbose           Toggle verbose mode. If no output filename was\n"
  417      "                          specified at the command line, verbose mode\n"
  418      "                          will automatically be turned off, in order for\n"
  419      "                          output messages not to interfere with the\n"
  420      "                          generated Encapsulated PostScript code.\n"
  421      "                          Default: off\n");
  422      fprintf(stderr,
  423        "  -h, --help        Display this help message and exit clean\n");
  424     fprintf(stderr,
  425      "Copyright (C) 2004 Fredrik Jonsson <jonsson@@uni-wuppertal.de>\n");
  426   }
  427   
  428   @ The |dvector()| routine allocate a real-valued vector of double precision,
  429   with vector index ranging from |nl| to |nh|.
  430   
  431   @<Routine for allocation of double vectors@>=
  432   double *dvector(long nl, long nh) {
  433      double *v;
  434      v=(double *)malloc((size_t) ((nh-nl+2)*sizeof(double)));
  435      if (!v) {
  436         fprintf(stderr,"Error: Allocation failure in dvector()\n");
  437         exit(FAILURE);
  438      }
  439      return v-nl+1;
  440   }
  441   
  442   @ The |dmatrix()| routine allocate a real-valued matrix of double precision,
  443   with row index ranging from |nrl| to |nrh|, and column index ranging from
  444   |ncl| to |nch|.
  445   
  446   @<Routine for allocation of double matrices@>=
  447   double **dmatrix(long nrl, long nrh, long ncl, long nch) {
  448      long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  449      double **m;
  450      m=(double **) malloc((size_t)((nrow+1)*sizeof(double*)));
  451      if (!m) {
  452         fprintf(stderr,"%s: Allocation failure 1 in dmatrix() routine!\n",
  453            progname);
  454         exit(FAILURE);
  455      }
  456      m += 1;
  457      m -= nrl;
  458      m[nrl]=(double *) malloc((size_t)((nrow*ncol+1)*sizeof(double)));
  459      if (!m[nrl]) {
  460         fprintf(stderr,"%s: Allocation failure 2 in dmatrix() routine!\n",
  461            progname);
  462         exit(FAILURE);
  463      }
  464      m[nrl] += 1;
  465      m[nrl] -= ncl;
  466      for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
  467      return m;
  468   }
  469   
  470   @ The |free_dvector()| routine release the memory occupied by the
  471   real-valued vector |v[nl..nh]|.
  472   
  473   @<Routine for deallocation of double vectors@>=
  474   void free_dvector(double *v, long nl, long nh) {
  475      free((char*) (v+nl-1));
  476   }
  477   
  478   @ The |free_dmatrix()| routine release the memory occupied by the
  479   real-valued matrix |m[nrl..nrh][ncl..nch]|.
  480   
  481   @<Routine for deallocation of double matrices@>=
  482   void free_dmatrix(double **m, long nrl, long nrh, long ncl, long nch) {
  483      free((char*) (m[nrl]+ncl-1));
  484      free((char*) (m+nrl-1));
  485   }
  486   
  487   @ The |load_matrix()| routine takes as input a character string
  488   |inputfilename|, specifying a regular text file of ASCII data stored
  489   as a matrix, and returns a pointer |m| to a matrix of double precision,
  490   containing the numerical values as appearing if the text file.
  491   The routine also automatically scans the input matrix size, and returns the
  492   number of rows in |nr| and the number of columns in |nc|.
  493   The number of columns is determined as the number of elements in the first
  494   row of data of the supplied text file. All subsequent rows are assumed to
  495   contain exactly the same number of elements; if this is not the case, an
  496   error message will be displayed on standard terminal output.
  497   The minimum and maximum elements found in the matrix are returned in the
  498   variables |min| and |max|, respectively.
  499   
  500   Example of usage:
  501   \medskip
  502   {\obeyspaces\obeylines\tt
  503   ~   double **imagematrix,min,max;
  504   ~   long int nr,nc;
  505   ~   imagematrix=load\_matrix("image.dat",\&nr,\&nc,\&min,\&max);
  506   ~   fprintf(stdout,"Detected \%ld rows and \%ld columns of data.\\n",nr,nc);
  507   ~   fprintf(stdout,"Minimum element: \%f\\n",min);
  508   ~   fprintf(stdout,"Maximum element: \%f\\n",max);
  509   }
  510   \bigskip
  511   
  512   @<Routine for loading matrix data from text file@>=
  513   char validchar(char ch) {
  514      return(isalnum(ch)||(ch=='+')||(ch=='-')||(ch=='.'));
  515   }
  516   
  517   double **load_matrix(char inputfilename[],long *nr,long *nc,
  518         double *min,double *max) {
  519      FILE *fpin=NULL;
  520      char tmpch;
  521      long j,k,nrt,nct;
  522      double tmpd,**m,tmin,tmax;
  523      if ((fpin=fopen(inputfilename,"r")) == NULL) {
  524         fprintf(stderr,"%s: Could not open file %s for reading!\n",
  525            progname,inputfilename);
  526         exit(FAILURE);
  527      }
  528   
  529      fseek(fpin,0L,SEEK_SET);
  530      fscanf(fpin,"%lf",&tmpd);
  531      tmin=tmpd; /* initialize memory for minimum element */
  532      tmax=tmpd; /* initialize memory for maximum element */
  533   
  534      fseek(fpin,0L,SEEK_SET);
  535      nct=0; /* initialize column counter */
  536      while ((tmpch=getc(fpin))!='\n') { /* determine column size |nc| */
  537         ungetc(tmpch,fpin);
  538         while ((tmpch=getc(fpin))==' '); /* get rid of any leading blanks */
  539         ungetc(tmpch,fpin);
  540         while (validchar(tmpch=getc(fpin))); /* scan pass field for valid char */
  541         ungetc(tmpch,fpin);
  542         nct++;
  543         while ((tmpch=getc(fpin))==' '); /* get read of any trailing blanks */
  544         ungetc(tmpch,fpin);
  545      }
  546   
  547      fseek(fpin,0L,SEEK_SET);
  548      nrt=0; /* initialize row counter */
  549      while ((tmpch=getc(fpin))!=EOF) { /* determine row size |nr| */
  550         ungetc(tmpch,fpin);
  551         for (k=1;k<=nct;k++) fscanf(fpin,"%lf",&tmpd);
  552         nrt++;
  553         tmpch=getc(fpin);
  554         while ((tmpch==' ')||(tmpch=='\n')) tmpch=getc(fpin);
  555         if (tmpch!=EOF) ungetc(tmpch,fpin);
  556      }
  557      m=dmatrix(1,nrt,1,nct);
  558   
  559      fseek(fpin,0L,SEEK_SET);
  560      for (j=1;j<=nrt;j++) { /* for all rows, ... */
  561         for (k=1;k<=nct;k++) { /* and for all columns, ... */
  562            fscanf(fpin,"%lf",&tmpd);
  563            m[j][k]=tmpd;
  564            if (tmpd<tmin)
  565               tmin=tmpd;
  566            else if (tmpd>tmax)
  567               tmax=tmpd;
  568         }
  569      }
  570      fclose(fpin);
  571      *nr=nrt;
  572      *nc=nct;
  573      *min=tmin;
  574      *max=tmax;
  575      return m;
  576   }
  577   
  578   @ The |unload_matrix()| routine simply releases memory previously allocated
  579   by the |load_matrix()| routine.
  580   
  581   @<Routine for unloading matrix data previously loaded from text file@>=
  582   void unload_matrix(double **m,long nr,long nc) {
  583      free_dmatrix(m,1,nr,1,nc); /* yes, it is this simple... */
  584   }
  585   
  586   @*Declaration of local variables of the |main| program.
  587   
  588   @<Local variables@>=
  589      double **imagematrix,min,max,dx,dy,llx,lly,urx,ury;
  590      double imagewidth,imageheight,imagexcenter,imageycenter;
  591      double linethickness=DEFAULT_LINETHICKNESS;
  592      time_t now=time(NULL);
  593      long int j,k,nr,nc;
  594      int no_arg,bbllx,bblly,bburx,bbury;
  595      FILE *fpout=NULL;
  596      char inputfilename[256]="",outputfilename[256]="";
  597      short verbose=0,write_floatform=0,write_frame=1;
  598      short infile_specified=0, outfile_specified=0, parse_data_sequentially=1;
  599      short write_title=0;
  600      short pixel_generation_mode=COMPACTIFIED_PIXELCODE;
  601      short comments_in_postscript=1;
  602   
  603   @*Parsing command line options. All input parameters are passed to the
  604   program through command line options and arguments to the program.
  605   The syntax of command line options is listed
  606   whenever the program is invoked without any options, or if the {\tt --help}
  607   option is specified at startup.
  608   
  609   @<Parse command line@>=
  610   {
  611      progname=argv[0];
  612      no_arg=argc;
  613      while(--argc) {
  614         if(!strcmp(argv[no_arg-argc],"-o") ||
  615            !strcmp(argv[no_arg-argc],"--outputfile")) {
  616            --argc;
  617            strcpy(outputfilename,argv[no_arg-argc]);
  618            outfile_specified=1;
  619         } else if(!strcmp(argv[no_arg-argc],"-i") ||
  620                   !strcmp(argv[no_arg-argc],"--inputfile")) {
  621            --argc;
  622            strcpy(inputfilename,argv[no_arg-argc]);
  623            infile_specified=1;
  624         } else if ((!strcmp(argv[no_arg-argc],"-f"))||
  625                    (!strcmp(argv[no_arg-argc],"--floatform"))) {
  626            write_floatform=(write_floatform?0:1);
  627            if (verbose) fprintf(stdout,"%s: Using floating number output.\n",
  628               progname);
  629         } else if ((!strcmp(argv[no_arg-argc],"-r"))||
  630                    (!strcmp(argv[no_arg-argc],"--writeframe"))) {
  631            write_frame=(write_frame?0:1);
  632         } else if (!strcmp(argv[no_arg-argc],"--commmented_postscript")) {
  633            comments_in_postscript=1;
  634         } else if (!strcmp(argv[no_arg-argc],"--uncommmented_postscript")) {
  635            comments_in_postscript=0;
  636         } else if (!strcmp(argv[no_arg-argc],"--compactified_pixelcode")) {
  637            pixel_generation_mode=COMPACTIFIED_PIXELCODE;
  638         } else if (!strcmp(argv[no_arg-argc],"--extensive_pixelcode")) {
  639            pixel_generation_mode=EXTENSIVE_PIXELCODE;
  640         } else if(!strcmp(argv[no_arg-argc],"-v") ||
  641                   !strcmp(argv[no_arg-argc],"--verbose")) {
  642            verbose=(verbose?0:1);
  643         } else if(!strcmp(argv[no_arg-argc],"-s") ||
  644                   !strcmp(argv[no_arg-argc],"--sequential")) {
  645            parse_data_sequentially=(parse_data_sequentially?0:1);
  646         } else {
  647            fprintf(stderr,"%s: Unknown option '%s'.\n",
  648               progname,argv[no_arg-argc]);
  649            exit(FAILURE);
  650         }
  651      }
  652      if (!outfile_specified) verbose=0; /* terminal output EPS should be clean */
  653   }
  654   
  655   @*Opening and closing files for data output.
  656   
  657   @ Open files for reading and writing.
  658   
  659   @<Open files@>=
  660   {
  661      if (outfile_specified) {
  662         if ((fpout=fopen(outputfilename,"w")) == NULL) {
  663            fprintf(stderr,"%s: Could not open file %s for writing!\n",
  664               progname,outputfilename);
  665            exit(FAILURE);
  666         }
  667         fseek(fpout,0L,SEEK_SET);
  668      } else {
  669         if (verbose)
  670            fprintf(stdout,"%s: No output file specified. (Writing to stdout).\n",
  671               progname);
  672      }
  673   }
  674   
  675   @ Loading the text file into memory. In this first step, the specified input
  676   text file is opened, and is loaded into memory allocated by the |dmatrix|
  677   routine. The memory area is accessed via the pointer |**imagematrix|, which
  678   is the basic variable used later on by the blocks that write the Encapsulated
  679   PostScript image to file. After the data is loaded, the input file is closed.
  680   
  681   @<Load text file into image matrix@>=
  682   {
  683      if (infile_specified) {
  684         if (verbose) fprintf(stderr,"%s: Loading data from file %s.\n",
  685            progname,inputfilename);
  686         imagematrix=load_matrix(inputfilename,&nr,&nc,&min,&max);
  687         if (verbose) {
  688            fprintf(stdout,
  689               "%s: Detected %ld rows and %ld columns of data in file '%s'.\n",
  690                  progname,nr,nc,inputfilename);
  691            fprintf(stdout,
  692               "%s: Maximum element in '%s': %f\n",progname,inputfilename,max);
  693            fprintf(stdout,
  694               "%s: Minimum element in '%s': %f\n",progname,inputfilename,min);
  695         }
  696      } else {
  697         fprintf(stderr,"%s: Error: Specify an input filename.\n",progname);
  698         showsomehelp();
  699         exit(FAILURE);
  700      }
  701   }
  702   
  703   @ Normalize the image matrix. In order to write a properly scaled Encapsulated
  704   PostScript image to file, the loaded data need to be normalized, so that the
  705   elements arenumerical values between 0 and 1.
  706   
  707   @<Normalize image matrix@>=
  708   {
  709      if (verbose) fprintf(stdout,"%s: Normalizing image matrix.\n",progname);
  710      for (j=1;j<=nr;j++) { /* for all rows, ... */
  711         for (k=1;k<=nc;k++) { /* and for all columns, ... */
  712            imagematrix[j][k]=imagematrix[j][k]-min;
  713            imagematrix[j][k]=imagematrix[j][k]/(max-min);
  714         }
  715      }
  716   }
  717   
  718   @ Initialize the parameters to be used for the Encapsulated PostScript image.
  719   The parameters to be set prior to the calculation of positioning of the
  720   individual pixels of the image are the corner coordinates for the bounding box.
  721   The $x$-height and $y$-width of the image are generally scaled such that
  722   the aspect ratio of the image is left invariant under scaling of any of the
  723   coordinate axes.
  724   
  725   By default, the program will use the width as reference for scaling the height
  726   of the image, to give an aspect ratio (height/width) that leaves the individual
  727   pixels as squares. If, however, the program finds that the calculated image
  728   height exceed the maximum allowed, then the height will be fixed to its maximum
  729   value, instead scaling the width of the image (to still give an equal aspect
  730   ratio).
  731   
  732   The values here used for the maximum extents of the picture are based on that
  733   for an A4 paper, the limiting bounding box is between the lower left corner
  734   at~$(0,0)$ pt and upper right corner at~$(594,841)$ pt.
  735   
  736   \bigskip
  737   \centerline{\epsfxsize=114.58mm\epsfbox{pagelayt/pagelayt.1}}\medskip\nobreak
  738   \centerline{Figure 2. The page layout and definitions as used for the
  739    initialization of the Encapsulated PostScript image.}
  740   
  741   
  742   @<Initialize parameters of Encapsulated PostScript image@>=
  743   {
  744      imagewidth=((double)(DEFAULT_IMAGE_WIDTH));
  745      imageheight=(((double)nr)/((double)nc))*((double)(DEFAULT_IMAGE_WIDTH));
  746      imagexcenter=DEFAULT_IMAGE_XCENTER;
  747      imageycenter=DEFAULT_IMAGE_YCENTER;
  748      if (imageheight>MAXIMUM_IMAGE_HEIGHT) {
  749         if (verbose) {
  750            fprintf(stdout,"%s: Warning. I found that the height of ",progname);
  751            fprintf(stdout,"the image exceeds its maximum\n");
  752            fprintf(stdout,"%s: value of %d pt.\n",
  753               progname,((int)MAXIMUM_IMAGE_HEIGHT));
  754            fprintf(stdout,"%s: Will now instead scale the width of the image.\n",
  755               progname);
  756         }
  757         imageheight=MAXIMUM_IMAGE_HEIGHT;
  758         imagewidth=(((double)nc)/((double)nr))*imageheight;
  759      } else {
  760         if (verbose) {
  761            fprintf(stdout,"%s: Image height automatically scaled to ",progname);
  762            fprintf(stdout,"width (to give equal aspect ratio).\n");
  763         }
  764      }
  765      bbllx=imagexcenter-imagewidth/2.0;
  766      bblly=imageycenter-imageheight/2.0;
  767      bburx=imagexcenter+imagewidth/2.0;
  768      bbury=imageycenter+imageheight/2.0;
  769   }
  770   
  771   @ Write the leading blocks of Encapsulated PostScript code.
  772   If the flag |pixel_generation_mode| is set to |COMPACTIFIED PIXELCODE|, then
  773   an additional routine for the generation of the individual pixels will be
  774   added just after the comments in the preamble; otherwise, the generated code
  775   will be self-contained in the sense that the individual pixels are defined
  776   as free-standing drawing statements in the code.
  777   Notice that the type of output stream (terminal output or file pointer,
  778   depending on the options present at the command line at startup of the
  779   program) is determined by the current definition provided by |OUTSTREAM|.
  780   Notice that the string returned by the |ctime()| routine ends with a linefeeed.
  781   
  782   The blocks dealing with the definition of the PostScript routine for a
  783   more ``compactified'' output code clearly deserves some more detailed
  784   description.
  785   The syntax for drawing an individual pixel, determined by the bounding box
  786   given by its lower left and upper right corners $(x_{\rm ll},y_{\rm ll})$
  787   and $(x_{\rm ur},y_{\rm ur})$ is\par\medskip
  788   {\narrower\narrower{\tt /drawpixel} $\langle|llx|\rangle$ $\langle|lly|\rangle$
  789    $\langle|urx|\rangle$ $\langle|ury|\rangle$ $\langle|w|\rangle$,\par}
  790   \medskip\noindent
  791   where $|llx|=x_{\rm ll}$, $|lly|=y_{\rm ll}$,
  792   $|urx|=x_{\rm ur}$, and $|ury|=y_{\rm ur}$.
  793   This definition is illustrated in Fig.~3 below.
  794   In this description of the syntax, $|w|\in[0,1]$ is the whiteness value of
  795   the pixel, with 0 corresponding to black, and 1 corresponding to white.
  796   \bigskip
  797   \centerline{\epsfxsize=45.0mm\epsfbox{pixbb/pixbb.1}}\medskip\nobreak
  798   \centerline{Figure 3. Illustration of the definition of a pixel in terms
  799     of its lower left and upper right corners.}
  800   \bigskip
  801   In the PostScript routine {\tt /drawpixel}, the following commands of the
  802   PostScript languange are used for manipulation of the stack:
  803   \medskip
  804   \oitem[{\tt dup}]{Duplicates the bottom element in the stack, and then pushes
  805    it into the stack. This operation is similar to the ENTER as used in reverse
  806    polish notation employed in, for example, Hewlett--Packard calculators.}
  807   
  808   \oitem[{\tt exch}]{Interchanges the two bottom-most elements in the stack.
  809    This operation is identical to SWAP.}
  810   
  811   \oitem[$\langle m\rangle$ $\langle n\rangle$ {\tt roll}]{Rolls down the~$m$
  812   bottom-most elements of the stack $n$ times, that is to say, applying cyclic
  813   permutation $n$ times on the first $m$ elements.
  814   In analogy with the ROLLD operation of reverse polish notation of
  815   Hewlett--Packard calculators, this is identical to executing the operation
  816   ``$m$ ROLLD'' exactly $n$ times.
  817   Notice that $\langle m\rangle$ $\langle m\rangle$ {\tt roll} always just gives
  818   the identity operation on the stack for arbitrary $m$ (of course provided
  819   that~$m$ is not greater than the number of elements that currently are present
  820   in the stack).
  821   
  822   @<Write preamble of Encapsulated PostScript image@>=
  823   {
  824      fprintf(OUTSTREAM,"%%!PS-Adobe-2.0 EPSF-1.2\n");
  825      fprintf(OUTSTREAM,"%%%%BoundingBox: %d %d %d %d\n",bbllx,bblly,bburx,bbury);
  826      fprintf(OUTSTREAM,"%%%%Creator: epsimg %s",VERSION_NUMBER);
  827      fprintf(OUTSTREAM," Copyright (C) 2004 Fredrik Jonsson\n");
  828      if (outfile_specified)
  829         fprintf(OUTSTREAM,"%%%%Title: %s\n",outputfilename);
  830      else
  831         fprintf(OUTSTREAM,"%%%%Title: (image written to stdout)\n");
  832      fprintf(OUTSTREAM,"%%%%CreationDate: %s",ctime(&now));
  833      fprintf(OUTSTREAM,"%%%%Pages: 1\n");
  834      fprintf(OUTSTREAM,"%%%%EndProlog\n");
  835      fprintf(OUTSTREAM,"%%%%Pages: 1\n");
  836      fprintf(OUTSTREAM,"%%%%Page: 1 1\n");
  837      if (pixel_generation_mode==COMPACTIFIED_PIXELCODE) {
  838         if (comments_in_postscript) {
  839            fprintf(OUTSTREAM,"%%\n");
  840            fprintf(OUTSTREAM,"%% Routine for duplicating the bottom-most pair");
  841            fprintf(OUTSTREAM," of elements in the stack.");
  842            fprintf(OUTSTREAM,"%%\n");
  843         }
  844         fprintf(OUTSTREAM,"/dupc {dup 3 2 roll dup 4 1 roll exch} bind def");
  845         if (comments_in_postscript) {
  846            fprintf(OUTSTREAM,"%%\n");
  847            fprintf(OUTSTREAM,"%% Routine for calculating the lower right corner");
  848            fprintf(OUTSTREAM," coordinates of the pixel.\n");
  849            fprintf(OUTSTREAM,"%% The syntax is simply '<llx> <lly> <urx> <ury> ");
  850            fprintf(OUTSTREAM," lrc', where (<llx>,<lly>)\n");
  851            fprintf(OUTSTREAM,"%% and (<urx>,<ury>) are the");
  852            fprintf(OUTSTREAM," lower left and upper right corner coordinates\n");
  853            fprintf(OUTSTREAM,"%% of the pixel. The resulting (<lrx>,<lry>) pair");
  854            fprintf(OUTSTREAM," are after the calculation\n%% pushed onto the");
  855            fprintf(OUTSTREAM," stack, preserving the previously present stack");
  856            fprintf(OUTSTREAM," at above\n%% levels.\n");
  857            fprintf(OUTSTREAM,"%%\n");
  858         }
  859         fprintf(OUTSTREAM,"/lrc {4 1 roll dup 5 2 roll dup 5 -1 roll exch");
  860         fprintf(OUTSTREAM," 4 2 roll 6 2 roll} bind def\n");
  861         fprintf(OUTSTREAM,"/ulc {4 3 roll dup 5 2 roll dup 6 -1 roll exch}");
  862         fprintf(OUTSTREAM," bind def\n");
  863         if (comments_in_postscript) {
  864            fprintf(OUTSTREAM,"%%\n");
  865            fprintf(OUTSTREAM,"%% Routine for drawing individual pixels\n");
  866            fprintf(OUTSTREAM,"%%\n");
  867         }
  868         fprintf(OUTSTREAM,"/pixelstack {lrc 6 2 roll ulc 4 2 roll 8 4 roll");
  869         fprintf(OUTSTREAM," dupc 10 2 roll} bind def\n");
  870         fprintf(OUTSTREAM,"/drawpixel {setgray pixelstack newpath moveto lineto\n");
  871         fprintf(OUTSTREAM," lineto lineto lineto closepath fill} bind def\n");
  872   
  873   
  874         if (comments_in_postscript) {
  875            fprintf(OUTSTREAM,"%%\n");
  876            fprintf(OUTSTREAM,"%% The dp routine is short-hand for drawpixel\n");
  877            fprintf(OUTSTREAM,"%%\n");
  878         }
  879         fprintf(OUTSTREAM,"/dp {drawpixel} bind def\n");
  880   
  881   
  882      }
  883   }
  884   
  885   @ Write the body of Encapsulated PostScript code.
  886   
  887   @<Write body of Encapsulated PostScript image@>=
  888   {
  889      if (parse_data_sequentially) {
  890         @<Write body of sequential Encapsulated PostScript image@>@;
  891      } else {
  892         @<Write body of partitioned Encapsulated PostScript image@>@;
  893      }
  894   }
  895   
  896   @ Write sequential body of Encapsulated PostScript code.
  897   The {\tt moveto} sets the current starting point of each pixel.
  898   The path of the boundary of each pixel is traversed in counter-clockwise
  899   direction, starting in the lower left corner of each pixel.
  900   Here |(llx,lly)| give the $(x,y)$-coordinates of the lower left corner of
  901   the pixel, while |(urx,ury)| give the $(x,y)$-coordinates of the upper right
  902   corner.
  903   
  904   @<Write body of sequential Encapsulated PostScript image@>=
  905   {
  906      dx=((double)(bburx-bbllx))/((double)nc);
  907      dy=((double)(bbury-bblly))/((double)nr);
  908      for (j=1;j<=nr;j++) {
  909         lly=((double)bblly)+((double)(j-1))*dy;
  910         ury=lly+dy*(1.0+8.0e-2);;
  911         for (k=1;k<=nc;k++) {
  912            llx=bbllx+((double)(k-1)*dx);
  913            urx=llx+dx*(1.0+8.0e-2);
  914            if (pixel_generation_mode==COMPACTIFIED_PIXELCODE) {
  915               fprintf(OUTSTREAM,"%1.2f %1.2f %1.2f %1.2f %1.3f dp\n",
  916                  llx,lly,urx,ury,imagematrix[j][k]);
  917            } else {
  918               fprintf(OUTSTREAM,"%1.3f setgray\n",imagematrix[j][k]);
  919               fprintf(OUTSTREAM,"newpath %1.2f %1.2f moveto\n",llx,lly);
  920               fprintf(OUTSTREAM," %1.2f %1.2f lineto",urx,lly);
  921               fprintf(OUTSTREAM," %1.2f %1.2f lineto\n",urx,ury);
  922               fprintf(OUTSTREAM," %1.2f %1.2f lineto",llx,ury);
  923               fprintf(OUTSTREAM," %1.2f %1.2f lineto closepath fill\n",llx,lly);
  924            }
  925         }
  926      }
  927      if (0==1) { /* for debugging purposes only */
  928         for (j=1;j<=nr;j++) {
  929            for (k=1;k<=nc;k++) {
  930               fprintf(stdout,"%2.4f  ",imagematrix[j][k]);
  931            }
  932            fprintf(stdout,"\n");
  933         }
  934      }
  935   }
  936   
  937   @ Write partitioned body of Encapsulated PostScript code.
  938   
  939   @<Write body of partitioned Encapsulated PostScript image@>=
  940   {
  941      fprintf(stdout,
  942         "Not yet finished with non-sequential partitioning of data\n");
  943      exit(-1);
  944   }
  945   
  946   @ Write the blocks ending the Encapsulated PostScript code.
  947   
  948   @<Write closing of Encapsulated PostScript image@>=
  949   {
  950      if (write_frame) { /* write frame corresponding to bounding box */
  951         fprintf(OUTSTREAM,"0 setgray 0 %1.2f dtransform truncate ",linethickness);
  952         fprintf(OUTSTREAM,"idtransform setlinewidth pop\n");
  953         fprintf(OUTSTREAM," [] 0 setdash 1 setlinejoin 10 setmiterlimit\n");
  954         fprintf(OUTSTREAM,"newpath %d %d moveto\n",bbllx,bblly);
  955         fprintf(OUTSTREAM," %d %d lineto",bburx,bblly);
  956         fprintf(OUTSTREAM," %d %d lineto\n",bburx,bbury);
  957         fprintf(OUTSTREAM," %d %d lineto",bbllx,bbury);
  958         fprintf(OUTSTREAM," %d %d lineto closepath stroke\n",bbllx,bblly);
  959      }
  960      if (write_title) {
  961         fprintf(stderr,"Still to be finished!!\n");
  962         exit(-1);
  963         fprintf(OUTSTREAM,"%%IncludeResource: font Helvetica\n");
  964         fprintf(OUTSTREAM,"/Helvetica /WindowsLatin1Encoding 120 FMSR\n");
  965   
  966         fprintf(OUTSTREAM,"2345 2372 moveto\n");
  967         fprintf(OUTSTREAM,"(Intensity distribution in observation plane) s\n");
  968   
  969         fprintf(OUTSTREAM,"504 2372 moveto -90 rotate\n");
  970         fprintf(OUTSTREAM,"(y [) s\n");
  971         fprintf(OUTSTREAM,"90 rotate\n");
  972   
  973         fprintf(OUTSTREAM,"%%IncludeResource: font Symbol\n");
  974         fprintf(OUTSTREAM,"/Symbol /WindowsLatin1Encoding 120 FMSR\n");
  975   
  976         fprintf(OUTSTREAM,"504 2540 moveto -90 rotate\n");
  977         fprintf(OUTSTREAM,"(m) s\n");
  978         fprintf(OUTSTREAM,"90 rotate\n");
  979         fprintf(OUTSTREAM,"504 2372 moveto -90 rotate\n");
  980         fprintf(OUTSTREAM,"(]) s\n");
  981         /* AND SO ON, IN THIS STYLE .... */
  982   
  983      }
  984      fprintf(OUTSTREAM,"showpage\n");
  985      fprintf(OUTSTREAM,"%%%%EOF\n");
  986   }
  987   
  988   
  989   @ Deallocate memory occupied by the image matrix.
  990   
  991   @<Deallocate image matrix@>=
  992   {
  993      unload_matrix(imagematrix,nr,nc);
  994   }
  995   
  996   
  997   @ Close all open files.
  998   
  999   @<Close files@>=
 1000   {
 1001      fclose(fpout);
 1002   }
 1003   
 1004   @*Index.
 1005   

Return to previous page

Generated by ::viewsrc::

Last modified Wednesday 15 Feb 2023