Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

cpxfiddle.cc

Go to the documentation of this file.
00001 /****************************************************************
00002  * cpxfiddle -- fiddle around with complex files.               *
00003  * kampes@baarda: make -n cpxfiddle                             *
00004  *      g++ -O -c -ocpxfiddle.o cpxfiddle.c                     *
00005  *      g++ -O cpxfiddle.o -o cpxfiddle                         *
00006  *                                                              *
00007  * BK 10-May-2000                                               *
00008  * $Revision: 3.10 $  $Date: 2004/01/20 12:58:57 $              *
00009  *                                                              *
00010  * TODO:                                                        *
00011  *  - output binary -ofloat add -oshort to crop slc's           *
00012  #%// BK 01-Feb-2001 done.                                      *
00013  *  - -B (swap bytes)                                           *
00014  #%// BK 12-Mar-2001                                            *
00015  *  - band interleaved input formats                            *
00016  *  - -q(uiet)                                                  *
00017  *  - -o sunraster -q mag: rescale etc.                         *
00018  *  - handle input defaults better, no lot of options.          *
00019  #%// BK 20-Apr-2001                                            *
00020  *  - -S scalebar for sunraster.                                *
00021  *  - -version info.                                            *
00022  *  BK 02 APRIL 2003 ********************************************
00023  *  - removed nocreate ios bit since g++ v3.2 does not know it  *
00024  *    (not standard C++?)                                       *
00025  *  - removed cout.setf(ios::binary) for same reason, though    *
00026  *    this means cpxfiddle does not work properly.  How can we  *
00027  *    write binary to stdout??                                  *
00028  *   cout.write((char*)&x, sizeof(x));// seems to work...       *
00029  *   it actually seems fine, i already did it like this...      *
00030  *  -bugfix when byteswapping and multilooking                  *
00031  *  -changed multilooking to normalize by number of looks       *
00032  *  -for HGT input, or R4 disguished as cpx, added some things. *
00033  #%// BK 05-Jan-2001                                            *
00034  * added skip header bytes                                      *
00035  #%// BK 17-Oct-2003                                            *
00036  ****************************************************************/
00037 
00038 using namespace std;
00039 #include <iostream>     // cerr etc
00040 #include <iomanip>      // binary to stdout
00041 #include <fstream>      // files
00042 #include <cmath>        // atan2
00043 #include <cstring>      // strcmp
00044 #include <unistd.h>     // getopt
00045 #include <cstdlib>      // exit
00046 #include <netinet/in.h> // ntohl htonl htons
00047 
00048 // #include <typeinfo.h>   // short type run time id, does not exist??
00049 // test...
00050 // #include <sys/types.h>
00051 //#include <machine/endian.h>
00052 
00053 
00054 // ====== version id -h ======
00055 //#define SWVERSION "v2.1 02-April-2003"
00056 //#define SWVERSION "v2.2 16-Jun-2003"
00057 #define SWVERSION "v2.3 20-Jan-2004"
00058 
00059 
00060 // ====== consts ======
00061 typedef unsigned char uchar;
00062 // ______ distinct flags ______
00063 const int FORMATR8  = 108;      // i/oformat -o float numbytes=%10 for new input
00064 const int FORMATR4  = 104;      // i/oformat -o float numbytes=%10 for new input
00065 const int FORMATI2  = 102;      // i/oformat -o float numbytes=%10 for new input
00066 const int FORMATUC1 = 101;      // i/oformat -o uchar numbytes=%10 for new input
00067 const int SUNRASTER = 201;      // i/oformat -o uchar + header + colmap +extrawidth(?)
00068 const int ASCII     = 999;      // oformat -o ascii
00069 // ______ formats are distinct, but format%10 must equal bytes per elem ______
00070 const int FORMATCUC1= 1;        // ==numbytes per real part of element %10
00071 const int FORMATCC1 = 11;       // ==numbytes per real part of element %10
00072 const int FORMATCI2 = 12;       // ==numbytes per real part of element %10
00073 const int FORMATCI4 = 14;       // ==numbytes per real part of element %10
00074 const int FORMATCR4 = 24;       // ==numbytes per real part of element %10
00075 const int FORMATCR8 = 28;       // ==numbytes per real part of element %10
00076 // ______ distinct flags ______
00077 const int MAGNITUDE = 51;       // output magnitude
00078 const int PHASE     = 52;       // output phase
00079 const int REALPART  = 53;       // output real part
00080 const int IMAGPART  = 54;       // output imag part
00081 const int NORMAL    = 55;       // output as is
00082 const int MIXED     = 56;       // output sunraster/uc1 mag/pha overlay
00083 // ______ should be -1||1 used in loops ______
00084 const int NOMIRROR  =  1;       // do no mirroring has to be  1 (used later)
00085 const int DOMIRROR  = -1;       // do mirroring has to be -1 (used later)
00086 
00087 // ====== Input variables ======
00088 struct commandlineinput
00089   {
00090   char  ifile[128];     // last argv
00091   int   linelength;     // -w mandatory
00092   float exponent;       // -e [1.0]
00093   float scale;          // -s [1.0]
00094   int   firstline;      // -l [1]
00095   int   lastline;       // -L [all]
00096   int   firstpixel;     // -p [1]
00097   int   lastpixel;      // -P [all]
00098   int   sublines;       // -S [1/1]
00099   int   subpixels;      // -S [1/1]
00100   int   multilookL;     // -M [1/1]
00101   int   multilookP;     // -M [1/1]
00102   int   iformat;        // -f ci2 [cr4]
00103   int   oformat;        // -o float uchar sunraster short [ascii]
00104   int   dooutput;       // -q [mag] phase real imag
00105   int   verbose;        // -V
00106   int   mirrorX;        // -m XY YX X Y
00107   int   mirrorY;        // -m XY YX X Y
00108   int   headerlength;   // -H 32 number of bytes to skip before matrix starts
00109   char  cmap[128];      // -c filename or identifier
00110   bool  dontohx;        // -B s swapbytes, big endian to host
00111   bool  dohtonx;        // -B b swapbytes, host to big endian.
00112   bool  scalebar;       // -b add scalebar for sunraster
00113   //bool  quiet;        // -q TODO, -V
00114   //
00115   // ______ Derived ______
00116   int   numlines;       // computed...
00117   int   bytesperelement;// sizeof real part
00118   int   bytesperpixel;  // sizeof complex pixel
00119   int   bytesperline;   // for seekg
00120   bool  realinput;      // for simplicity
00121   };
00122 
00123 
00124 // ====== Prototypes of functions in this file ======
00125 void shortexpl();
00126 void usage(char *programname);
00127 void synopsis(char *programname);
00128 bool handleinput(int argc, char* argv[], commandlineinput &input);
00129 template <class Type>
00130 void functie(Type, Type, const commandlineinput &input);
00131 void rescale(uchar *OUT, float *IN, const int numin,
00132   const float MIN, const float MAX, const float NEWMIN, const float NEWMAX);
00133 void rasterheader(unsigned long header[8], const int width, const int height);
00134 void makecmap(unsigned char CMAP[3][256], const commandlineinput &input);
00135 void makecmapmixed(unsigned char CMAP[3][256], const commandlineinput &input);
00136 
00137 
00138 
00139 
00140 /****************************************************************
00141  * main                                                         *
00142  ****************************************************************/
00143 int main(int argc,char* argv[])
00144   {
00145   // ====== Handle input ======
00146   // "what `which prog`"
00147   char ident[] = "@(#)Doris software, $Revision: 3.10 $, $Author: kampes $";
00148   //if (input.verbose)
00149   cerr << ident << endl;
00150   commandlineinput input;
00151   if (handleinput(argc,argv,input)==false) synopsis(argv[0]);
00152 
00153   // ______ Call template function to deal with different io ______
00154   char dummy = '1';
00155   switch (input.iformat)
00156     {
00157     case FORMATCC1:     // complex char
00158       functie(char(dummy),char(dummy),input);
00159       break;
00160     case FORMATUC1:     // byte, fall through
00161     case FORMATCUC1:    // unsigned complex char
00162       functie(uchar(dummy),uchar(dummy),input);
00163       break;
00164     case FORMATI2:      // short signed int, fall through
00165     case FORMATCI2:     // complex short integer
00166       functie(short(dummy),short(dummy),input);
00167       break;
00168     case FORMATCI4:     // complex integer
00169       functie(int(dummy),int(dummy),input);
00170       break;
00171     case FORMATR4:      // float, fall through
00172     case FORMATCR4:     // complex float
00173       functie(float(dummy),float(dummy),input);
00174       break;
00175     case FORMATR8:      // double, fall through
00176     case FORMATCR8:     // complex double
00177       functie(double(dummy),double(dummy),input);
00178       break;
00179     default: 
00180       cerr << argv[0] << ": PANIC: unknown format...\n";
00181     }
00182 
00183   // ====== Tidy up ======
00184   return 0;
00185   } // END main
00186 
00187 
00188 
00189 /****************************************************************
00190  * template read/comp/write function whole matrix               *
00191  * may be speeded up by defining a function readline, but       *
00192  * compiler can optimize this as well (?).                      *
00193  #%// BK 11-May-2000                                            *
00194  ****************************************************************/
00195 template <class Type>
00196 void functie(Type realpart, Type imagpart, const commandlineinput &input)
00197   {
00198   if (sizeof(Type) != input.bytesperelement) 
00199     {cerr << "PANIC: impossible...\n"; exit(1);}
00200   //ifstream inf(input.ifile, ios::in | ios::binary | ios::nocreate);
00201   ifstream inf(input.ifile, ios::in | ios::binary);
00202   if (!inf)
00203     {
00204     cerr << "cpxfiddle: ERROR: opening input file: " 
00205          << input.ifile << "\n";
00206     exit(1);
00207     }
00208 
00209   register int i,j,k,realindex,start;
00210   // ___ it seems this is not allowed in g++v3.2.  How to do it? ___
00211   // use new way if binary to stdout: cout.write((char*)&x, sizeof(x))
00212   //if (input.oformat!=ASCII) cout.write((char*)&x, sizeof(x));// binary to stdout!
00213   //if (input.oformat!=ASCII) cout.setf(ios::binary);   // !! binary to stdout
00214   //if (input.oformat!=ASCII) cout.setf(ios::binary);   // !! binary to stdout
00215   const float PI = 4.0*atan(1.0);
00216 
00217   // ______ read in the whole line (even if subsampling) 
00218   // ______ because simplicity for mirroring in X. (later multilooking?)
00219   // ______ fill output 0:numoutput as 2b written to stdout ______
00220   // ______ if MIXED: OUTPUT[1sthalf]==MAG, 2ndhalf==PHASE ______
00221   Type  *LINE;
00222   float *OUTPUT;                                        // 2* for NORMAL output
00223   LINE   = new Type[2*(input.lastpixel-input.firstpixel+1)];    // allocate memory
00224   OUTPUT = new float[2*(input.lastpixel-input.firstpixel+1)];   // allocate memory
00225 
00226   // ______ Allocate and set stuff for multilooking ______
00227   // ______ sublines = multilook set in 'handle input' ______
00228   Type  *LINEML;        // multilooked line
00229   if (input.multilookL != 1)    // ie. >1
00230     LINEML = new Type[2*(input.lastpixel-input.firstpixel+1)];    // allocate memory
00231 
00232   if (input.verbose)
00233     {
00234     int alloc = sizeof(LINE[0])   * 2 * (input.lastpixel-input.firstpixel+1) +
00235                 sizeof(OUTPUT[0]) * 2 * (input.lastpixel-input.firstpixel+1);
00236     if (input.multilookL != 1)
00237         alloc += sizeof(LINEML[0]) * 2 * (input.lastpixel-input.firstpixel+1);
00238     cerr << "cpxfiddle: INFO: Allocating " << int(alloc/1000.) << "KB\n";
00239     }
00240 
00241   // ______ Indices to loop forward/backward over file ______
00242   const int starti = (input.mirrorY==NOMIRROR) ? input.firstline  :  input.lastline;
00243         int stopi  = (input.mirrorY==NOMIRROR) ? input.lastline   : -input.firstline;
00244   const int plusi  = (input.mirrorY==NOMIRROR) ? input.sublines   : -input.sublines;
00245   const int startj = (input.mirrorX==NOMIRROR) ? input.firstpixel :  input.lastpixel;
00246         int stopj  = (input.mirrorX==NOMIRROR) ? input.lastpixel  : -input.firstpixel;
00247   const int plusj  = (input.mirrorX==NOMIRROR) ? input.subpixels  : -input.subpixels;
00248 
00249   // ______ Correct index for multilooking, avoid reading to far ______
00250   if (input.multilookL!=1)
00251     stopi = int((stopi/plusi) * plusi);
00252     //stopi = int(floor(stopi/plusi) * plusi);
00253   if (input.multilookP!=1)
00254     stopj = int((stopj/plusj) * plusj);
00255     //stopj = int(floor(stopj/plusj) * plusj);
00256 
00257 
00258   // ______ number of elements to output per line ______
00259   int numoutput = int(ceil(float(input.lastpixel-input.firstpixel+1.)/
00260                            float(input.subpixels)));
00261   if (input.multilookP!=1)
00262     numoutput = int(floor(float(input.lastpixel-input.firstpixel+1.)/
00263                   float(input.subpixels)));
00264   if (input.dooutput==NORMAL)
00265     {
00266     if (input.realinput == true)
00267       {
00268       if (input.verbose==true)
00269         {
00270         cerr << "cpxfiddle: INFO: real input format detected.\n";
00271         cerr << "cpxfiddle: INFO: Number of (real) output pixels: "
00272              << numoutput << "\n";
00273         }
00274       }
00275     else
00276       {
00277       if (input.verbose==true)
00278         {
00279         cerr << "cpxfiddle: INFO: Number of (complex) output pixels: "
00280              << numoutput << "\n";
00281         }
00282       numoutput*=2;     // output real&imag part, size of array.
00283       }
00284     }
00285   else
00286     cerr << "cpxfiddle: INFO: Number of output pixels: " << numoutput << "\n";
00287 
00288   // ______ number of elements output height ______
00289   int height = int(ceil(float(input.lastline-input.firstline+1.)/
00290                         float(input.sublines)));
00291   if (input.multilookL!=1)
00292     height = int(floor(float(input.lastline-input.firstline+1.)/
00293                        float(input.sublines)));
00294   if (input.verbose==true)
00295     cerr << "cpxfiddle: INFO: Number of output lines:  " << height << "\n";
00296 
00297 
00298   // ______ Write sunraster header (and cmap) if requested ______
00299   double meanmag   = -999999999.999;// to rescale sunraster magnitude image
00300   double min_input = +999999999.999;
00301   double max_input = -999999999.999;
00302   if (input.oformat==SUNRASTER)
00303     {
00304     // ______ Header (cmap length==256*3) ______
00305     unsigned long int HEADER[8];                // 8 long ints
00306     rasterheader(HEADER,numoutput,height);      // create header
00307     if (input.verbose==true)
00308       cerr << "Writing 32 byte header of SUNraster file.\n";
00309     /*
00310            << "\nmagic#:    " << ntohl(HEADER[0])
00311            << "\nwidth:     " << ntohl(HEADER[1])
00312            << "\nheight:    " << ntohl(HEADER[2])
00313            << "\ndepth:     " << ntohl(HEADER[3])
00314            << "\nlength:    " << ntohl(HEADER[4])
00315            << "\ntype:      " << ntohl(HEADER[5])
00316            << "\nmaptype:   " << ntohl(HEADER[6])
00317            << "\nmaplength: " << ntohl(HEADER[7])
00318            << endl;
00319     */
00320     cout.write((char*)&HEADER[0],32);           // binary to stdout
00321     // ______ Cmap ______
00322     // unsigned maplength = ntohl(HEADER[7]);   // 3 * length per color
00323     unsigned int maplength = 3*256;             // 3 * length per color
00324     unsigned char CMAP[3][256];                 // colormap see rasterheader
00325     if (input.dooutput==MIXED)
00326       makecmapmixed(CMAP,input);                // only [3][256]
00327     else
00328       makecmap(CMAP,input);                     // only [3][256]
00329     cout.write((char*)&CMAP[0],maplength);      // binary to stdout
00330 
00331     // ______ For magnitude output, get mean value approximately ______
00332     // ______ BK 4-apr-2001 ______
00333     if (input.dooutput==MAGNITUDE || input.dooutput==MIXED ||
00334         input.dooutput==NORMAL) // assume doris tricked for hgt.
00335       {
00336       meanmag         = 0.0;
00337       int numsamples  = 0;
00338       int samplesizeY = input.sublines;  // subsample per x lines...
00339       int samplesizeX = input.subpixels;
00340       int nX = (input.lastline-input.firstline)/samplesizeY;
00341       int nY = (input.lastpixel-input.firstpixel)/samplesizeX;
00342       while (nX*nY>250000) // 200x200 window is ok in general
00343         {
00344         samplesizeX *= 2;
00345         samplesizeY *= 3; // reading file iritating...
00346         nX = (input.lastline-input.firstline)/samplesizeY;
00347         nY = (input.lastpixel-input.firstpixel)/samplesizeX;
00348         }
00349       for (i=input.firstline; i<input.lastline; i+=samplesizeY)
00350         {
00351         start  = input.bytesperline*(i-1) +
00352                  (input.firstpixel-1)*input.bytesperpixel;
00353         start += input.headerlength;// account for header.
00354         inf.seekg(start,ios::beg);
00355         inf.read((char*)&LINE[0],
00356           (input.lastpixel-input.firstpixel+1)*input.bytesperpixel); 
00357         for (j=input.firstpixel; j<input.lastpixel; j+=samplesizeX)
00358           {
00359           numsamples++;
00360           realindex = 2*(j-input.firstpixel);           // index in LINE 
00361           realpart  = LINE[realindex];
00362           imagpart  = LINE[realindex+1];
00363           // ______ Swap bytes if -B option specified ______
00364           if (input.dontohx==true)
00365             {
00366             if (sizeof(Type)==sizeof(short))
00367               {
00368               realpart = ntohs(short(realpart));
00369               imagpart = ntohs(short(imagpart));
00370               }
00371             else if (sizeof(Type)==sizeof(int))
00372               {
00373               realpart = ntohl(short(realpart));
00374               imagpart = ntohl(short(imagpart));
00375               }
00376             }
00377           if (input.dohtonx==true)
00378             {
00379             if (sizeof(Type)==sizeof(short))
00380               {
00381               realpart = htons(short(realpart));
00382               imagpart = htons(short(imagpart));
00383               }
00384             else if (sizeof(Type)==sizeof(int))
00385               {
00386               realpart = htonl(short(realpart));
00387               imagpart = htonl(short(imagpart));
00388               }
00389             }
00390           if (input.exponent==1.)
00391             meanmag  += sqrt(float(realpart)*float(realpart)+
00392                              float(imagpart)*float(imagpart));
00393           else
00394             meanmag  += pow(sqrt(float(realpart)*float(realpart)+
00395                                  float(imagpart)*float(imagpart)),
00396                             input.exponent);
00397           // --- assume NORMAL input, unwrapped phase ---
00398           if (realpart<min_input) min_input = realpart;
00399           if (imagpart<min_input) min_input = imagpart;
00400           if (realpart>max_input) max_input = realpart;
00401           if (imagpart>max_input) max_input = imagpart;
00402           }
00403         }
00404       //meanmag = input.scale*meanmag/numsamples;// finally...
00405       meanmag = meanmag/numsamples;// finally...
00406       if (input.verbose==true)
00407         {
00408         cerr << "mean magnitude based on " << numsamples
00409              << " samples: " << meanmag << endl;
00410         cerr << "min magnitude based on " << numsamples
00411              << " samples: " << min_input << endl;
00412         cerr << "max magnitude based on " << numsamples
00413              << " samples: " << max_input << endl;
00414         }
00415       }
00416     }
00417 
00418   // ______ Obtain information for placing scalebar for sunraster ______
00419   int outputlinecnt  = 0;
00420   int scalebarheight = int(height/25.);         // of total height in output lines
00421   int scalebarwidth  = int(numoutput/5.);       // of total width in output pixels
00422   int line0scalebar  = height - 2*scalebarheight;       // position lower
00423   int lineNscalebar  = line0scalebar+scalebarheight;    // position
00424   int pixel0scalebar = numoutput -scalebarheight-scalebarwidth;// position right
00425 
00426   // ______ Swap bytes to host order ______
00427   if (input.dontohx==true)
00428     if (input.verbose==true)
00429       cerr << "Swapping bytes (big endian to host type, function ntohs/ntohl).\n";
00430   if (input.dohtonx==true)
00431     if (input.verbose==true)
00432       cerr << "Swapping bytes (host type to big endian, function htons/htonl).\n";
00433 
00434   // ______ 10% should be multiple of plusi ______
00435   bool giveprogress = (numoutput > 1000) ? true : false;
00436   if (input.verbose==false) giveprogress = false;
00437   int onepercent = int(floor(abs(starti-stopi)/100.));
00438   //if (giveprogress) while ((tenpercent%plusi)) tenpercent--;
00439   if (giveprogress) while ((onepercent%plusi)) onepercent--;
00440   int percent = 0;
00441 
00442   // _____ Do normlize by number of looks, but not TYPE _______
00443   double numlooks = double(input.multilookL)*double(input.multilookP);
00444   if (input.verbose==true)
00445     cerr << "cpxfiddle: INFO: Number of looks:         " << numlooks << "\n";
00446 
00447 
00448   // ====== Read file, compute output, write to stdout ======
00449   // for (i=input.firstline; i<=input.lastline; i+=input.sublines)
00450   // ______ mirrorY in loop initialization ______
00451   for (i=starti; i*input.mirrorY<=stopi; i+=plusi)      // forwards or backwards
00452     {
00453     if (giveprogress==true)
00454       {
00455       if (!((i-starti)%onepercent))
00456         {
00457         if (input.verbose==true)
00458           cerr << "\rprocessed: " << percent << "%";
00459         percent += 1;
00460         //percent += 10;
00461         }
00462       }
00463 
00464     // ______ start is just before line i to be read ______
00465     start  = input.bytesperline*(i-1) + (input.firstpixel-1)*input.bytesperpixel;
00466     start += input.headerlength;// account for header.
00467     inf.seekg(start,ios::beg);
00468     inf.read((char*)&LINE[0],(input.lastpixel-input.firstpixel+1)*input.bytesperpixel); 
00469 
00470     // ______ Swap bytes if -B option specified ______
00471     if (input.dontohx==true)
00472       {
00473       if (sizeof(Type)==sizeof(short))
00474         {
00475         for (k=0; k<2*(input.lastpixel-input.firstpixel+1); ++k)
00476           {
00477           LINE[k] = ntohs(short(LINE[k]));
00478           }
00479         }
00480       else if (sizeof(Type)==sizeof(int))
00481         {
00482         for (k=0; k<2*(input.lastpixel-input.firstpixel+1); ++k)
00483           {
00484           LINE[k] = ntohl(short(LINE[k]));
00485           }
00486         }
00487       else
00488         cerr << "seems wrong, -B and not 2B/4B type, ignoring.\n";
00489       }
00490     if (input.dohtonx==true)
00491       {
00492       if (sizeof(Type)==sizeof(short))
00493         {
00494         for (k=0; k<2*(input.lastpixel-input.firstpixel+1); ++k)
00495           {
00496           LINE[k] = htons(short(LINE[k]));
00497           }
00498         }
00499       else if (sizeof(Type)==sizeof(int))
00500         {
00501         for (k=0; k<2*(input.lastpixel-input.firstpixel+1); ++k)
00502           {
00503           LINE[k] = htonl(short(LINE[k]));
00504           }
00505         }
00506       else
00507         cerr << "seems wrong, -B and not type 2B/4B, ignoring.\n";
00508       }
00509 
00510 
00511     // ______ Do multilooking in line direction here ______
00512     for (int mll=1; mll<input.multilookL; ++mll)
00513       {
00514       // ______ Read next/previous line and add it to LINE ______
00515       start  = input.bytesperline*(i-1+(mll*input.mirrorY)) +
00516                (input.firstpixel-1)*input.bytesperpixel;
00517       start += input.headerlength;// account for header.
00518       inf.seekg(start,ios::beg);
00519       inf.read((char*)&LINEML[0],
00520         (input.lastpixel-input.firstpixel+1)*input.bytesperpixel); 
00521       for (int pix=0; pix<2*(input.lastpixel-input.firstpixel+1); ++pix)
00522         {
00523         // ______ Swap bytes if -B option specified ______
00524         if (input.dontohx==true)
00525           {
00526           if (sizeof(Type)==sizeof(short))
00527             LINEML[pix] = ntohs(short(LINEML[pix]));
00528           else if (sizeof(Type)==sizeof(int))
00529             LINEML[pix] = ntohl(short(LINEML[pix]));
00530           }
00531         if (input.dohtonx==true)
00532           {
00533           if (sizeof(Type)==sizeof(short))
00534             LINEML[pix] = htons(short(LINEML[pix]));
00535           else if (sizeof(Type)==sizeof(int))
00536             LINEML[pix] = htonl(short(LINEML[pix]));
00537           }
00538         // ______ Finally multilook ______
00539         LINE[pix] += LINEML[pix];       // add real and imag part
00540         }
00541       }
00542 
00543     // ______ Compute output, store in array OUTPUT ______
00544     // ______ multilook here in X (range) direction ______
00545     // ______ store in LINE[j,x,x,j,x,x,j,..]; j are multilooked values ______
00546     register int indexoutput = 0;                       // j is input index
00547     double dbl_real;// for normlaization with numlooks
00548     double dbl_imag;
00549     switch (input.dooutput)
00550       {
00551       case MAGNITUDE:
00552         // ______ j is index in pixel notation e[first,last] ______
00553         for (j=startj; j*input.mirrorX<=stopj; j+=plusj)  // forwards or backwards
00554           {
00555           realindex = 2*(j-input.firstpixel);           // index in LINE 
00556           realpart  = LINE[realindex];
00557           imagpart  = LINE[realindex+1];
00558           // ______ Multilook in X direction ______
00559           for (int mlp=1; mlp<input.multilookP; ++mlp)
00560             {
00561             realpart += LINE[realindex+  2*(mlp*input.mirrorX)];
00562             imagpart += LINE[realindex+1+2*(mlp*input.mirrorX)];
00563             }
00564           dbl_real = double(realpart) / numlooks;
00565           dbl_imag = double(imagpart) / numlooks;
00566           OUTPUT[indexoutput] = (input.exponent==1.) ?
00567             input.scale * sqrt(float(dbl_real*dbl_real+dbl_imag*dbl_imag)) :
00568             input.scale * pow(sqrt(float(dbl_real*dbl_real+dbl_imag*dbl_imag)),
00569                               input.exponent);
00570           indexoutput++;
00571           }
00572         break; // case
00573 
00574       case PHASE:
00575         for (j=startj; j*input.mirrorX<=stopj; j+=plusj)  // forwards or backwards
00576           {
00577           realindex = 2*(j-input.firstpixel);
00578           realpart  = LINE[realindex];
00579           imagpart  = LINE[realindex+1];
00580           // ______ Multilook in X direction ______
00581           for (int mlp=1; mlp<input.multilookP; ++mlp)  // number of ml pixels
00582             {
00583             realpart += LINE[realindex+  2*(mlp*input.mirrorX)];
00584             imagpart += LINE[realindex+1+2*(mlp*input.mirrorX)];
00585             }
00586           dbl_real = double(realpart) / numlooks;
00587           dbl_imag = double(imagpart) / numlooks;
00588           OUTPUT[indexoutput] = (input.exponent==1.) ?
00589             input.scale * atan2(float(dbl_imag),float(dbl_real)) :
00590             input.scale * pow(atan2(float(dbl_imag),float(dbl_real)),
00591                               input.exponent);
00592           indexoutput++;
00593           }
00594         break; // case
00595 
00596       case MIXED:
00597         // ______ OUTPUT[0:numoutput-1] for MAG ______
00598         // ______ OUTPUT[numoutput:2*numoutput-1] for PHASE ______
00599         // ______ j is index in pixel notation e[first,last] ______
00600         for (j=startj; j*input.mirrorX<=stopj; j+=plusj)  // forwards or backwards
00601           {
00602           realindex = 2*(j-input.firstpixel);           // index in LINE 
00603           realpart  = LINE[realindex];
00604           imagpart  = LINE[realindex+1];
00605           // ______ Multilook in X direction ______
00606           for (int mlp=1; mlp<input.multilookP; ++mlp)
00607             {
00608             realpart += LINE[realindex+  2*(mlp*input.mirrorX)];
00609             imagpart += LINE[realindex+1+2*(mlp*input.mirrorX)];
00610             }
00611           dbl_real = double(realpart) / numlooks;
00612           dbl_imag = double(imagpart) / numlooks;
00613           OUTPUT[indexoutput] = (input.exponent==1.) ?
00614             input.scale * sqrt(float(dbl_real*dbl_real+dbl_imag*dbl_imag)) :
00615             input.scale * pow(sqrt(float(dbl_real*dbl_real+dbl_imag*dbl_imag)),
00616                               input.exponent);
00617           // ______ PHASE in second half of output array (NO scale/exp) ______
00618           OUTPUT[indexoutput+numoutput] =
00619             atan2(float(dbl_imag),float(dbl_real));
00620           indexoutput++;
00621           }
00622         break; // case mixed
00623 
00624       case REALPART:
00625         for (j=startj; j*input.mirrorX<=stopj; j+=plusj)  // forwards or backwards
00626           {
00627           realindex = 2*(j-input.firstpixel);
00628           realpart  = LINE[realindex];
00629           // ______ Multilook in X direction ______
00630           for (int mlp=1; mlp<input.multilookP; ++mlp)  // number of ml pixels
00631             realpart += LINE[realindex+  2*(mlp*input.mirrorX)];
00632           dbl_real = double(realpart) / numlooks;
00633           OUTPUT[indexoutput] = (input.exponent==1.) ?
00634             input.scale * dbl_real :
00635             input.scale * pow(float(dbl_real),input.exponent);
00636           indexoutput++;
00637           }
00638         break; // case
00639 
00640       case IMAGPART:
00641         for (j=startj; j*input.mirrorX<=stopj; j+=plusj)  // forwards or backwards
00642           {
00643           realindex = 2*(j-input.firstpixel);
00644           imagpart  = LINE[realindex+1];
00645           // ______ Multilook in X direction ______
00646           for (int mlp=1; mlp<input.multilookP; ++mlp)  // number of ml pixels
00647             imagpart += LINE[realindex+1+2*(mlp*input.mirrorX)];
00648           dbl_imag = double(imagpart) / numlooks;
00649           OUTPUT[indexoutput] = (input.exponent==1.) ?
00650             input.scale * dbl_imag :
00651             input.scale * pow(float(dbl_imag),input.exponent);
00652           indexoutput++;
00653           }
00654         break; // case
00655       case NORMAL:
00656         for (j=startj; j*input.mirrorX<=stopj; j+=plusj)  // forwards or backwards
00657           {
00658           // report and bugfix by Dietrich Wanke, for r4 mirroring in X #%// BK 30-Jul-2003
00659           //realindex = 2*(j-input.firstpixel);
00660           //realindex = (input.iformat != FORMATR4) ? 2*(j-input.firstpixel) : 
00661           realindex = (input.realinput == false) ? 2*(j-input.firstpixel) : 
00662                                                      (j-input.firstpixel);
00663           realpart  = LINE[realindex];
00664           imagpart  = LINE[realindex+1];
00665           // ______ Multilook in X direction ______
00666           for (int mlp=1; mlp<input.multilookP; ++mlp)  // number of ml pixels
00667             {
00668             realpart += LINE[realindex+  2*(mlp*input.mirrorX)];
00669             imagpart += LINE[realindex+1+2*(mlp*input.mirrorX)];
00670             }
00671           dbl_real = double(realpart) / numlooks;
00672           dbl_imag = double(imagpart) / numlooks;
00673           OUTPUT[indexoutput] = (input.exponent==1.) ?
00674             input.scale * dbl_real :
00675             input.scale * pow(float(dbl_real),input.exponent);
00676           indexoutput++;
00677           // made conditional followingbugfix by Dietrich Wanke #%// BK 30-Jul-2003
00678           //if (input.iformat != FORMATR4)// made conditional for r4 output
00679           if (input.realinput == false)// made conditional for r4 output
00680             {
00681             OUTPUT[indexoutput] = (input.exponent==1.) ?
00682               input.scale * dbl_imag :
00683               input.scale * pow(float(dbl_imag),input.exponent);
00684             indexoutput++;
00685             }
00686           }
00687         break; // case
00688       default:
00689         cerr << "PANIC: impossible output request...\n";
00690       } // switch output type
00691 
00692     // ______ Ouptut to stdout, ______
00693     // ______ compiler moves switch outside loop for speed? ______
00694     outputlinecnt++;
00695     switch (input.oformat)
00696       {
00697       case ASCII:
00698         {
00699         for (k=0; k<numoutput; ++k)
00700           cout << OUTPUT[k] << " ";             // let compiler deal with format
00701         break;
00702         }
00703       case FORMATR4:
00704         {
00705         // ______ Write binary to stdout (redirect to file or pipe to next command) ______
00706         const int sizeoutput = sizeof(float);
00707         cout.write((char*)&OUTPUT[0],numoutput*sizeoutput);
00708         break;
00709         }
00710       case FORMATI2:
00711         {
00712         // ______ Write binary to stdout ______
00713         // ______ This is a cast, and not very smart, but works ______
00714         // BK 01-Feb-2001
00715         const int sizeoutput = sizeof(short);
00716         short *OUTPUTI2;
00717         OUTPUTI2 = new short[numoutput];        // allocate memory
00718           for (k=0; k<numoutput; ++k)
00719             OUTPUTI2[k] = short(OUTPUT[k]);
00720         cout.write((char*)&OUTPUTI2[0],numoutput*sizeoutput);
00721         break;
00722         }
00723       case SUNRASTER:
00724         {
00725         // ______ Header and colormap already written ______
00726         // ______ Fall through to UC1 ______
00727         }
00728       case FORMATUC1:
00729         {
00730         // ______ Rescale output [min,max] --> [0,255] ______
00731         // ______ only for -qphase for now ______
00732         const int sizeoutput = sizeof(char);            // output type is char
00733         uchar *OUT_UC;
00734         OUT_UC = new uchar[numoutput];
00735         switch (input.dooutput)
00736           {
00737           case NORMAL:
00738             {
00739             // ______ Assume someone is trying to plot a R4 or HGT file ______
00740             // ______ Fall through to PHASE for plotting______
00741             // ______But first adapt OUTPUT to range -pi,pi______
00742             // ______Because min/max may be unwrapped phase______
00743             for (int ii=0; ii<numoutput; ++ii)
00744               {
00745               if      (OUTPUT[ii]<min_input) OUTPUT[ii]=-PI;// avoid clipping
00746               else if (OUTPUT[ii]>max_input) OUTPUT[ii]= PI;// avoid clipping
00747               else OUTPUT[ii] = (OUTPUT[ii]-min_input)*
00748                                 (2.0*PI/(max_input-min_input))-PI;
00749               }
00750             // ______ Fall through to PHASE for plotting______
00751             }
00752           case PHASE:
00753             rescale(OUT_UC,OUTPUT,numoutput,-PI,PI,0,255);          // fill uc
00754             // ______ Add scalebar if requested ______
00755             // ______ by changing the data in lower right corner ______
00756             if (input.scalebar)
00757               {
00758               if (outputlinecnt>=line0scalebar && outputlinecnt<=lineNscalebar)
00759                 {
00760                 // ______ change the data to [0:255] ______
00761                 for (int ii=pixel0scalebar; ii<=pixel0scalebar+scalebarwidth; ++ii)
00762                   {
00763                   OUT_UC[ii]= uchar(float(ii-pixel0scalebar)*
00764                                     (255./float(scalebarwidth)));
00765                   }
00766                 }
00767               }
00768             break;
00769           case MAGNITUDE:
00770             {
00771             // ______ First convert output to float 16:255, ______
00772             // ______ then make integers. scale influences this. ______
00773             // ______ so a larger scale factor thresholds more ______
00774             // ______ data to max (white) ______
00775             for (int ii=0; ii<numoutput; ++ii)
00776               {
00777               OUTPUT[ii] *= (150./meanmag);// scaled mag now has mean==150
00778               if      (OUTPUT[ii]<16)  OUTPUT[ii]=16;
00779               else if (OUTPUT[ii]>255) OUTPUT[ii]=255;
00780               }
00781             rescale(OUT_UC,OUTPUT,numoutput,0,255,0,255);    // fill uc
00782             break;
00783             }
00784           case MIXED:
00785             {
00786             // ______ We have 2 arrays, magnitude: OUPUT, phase: OUT_PHA
00787             // ______ create OUTPUT = numcolorsphase*MAG+PHASE ______
00788             float *OUT_PHA;                     // temp. store phase here as float
00789             OUT_PHA = new float[numoutput];
00790             for (int ii=0; ii<numoutput; ++ii)
00791               {
00792               OUT_PHA[ii] = OUTPUT[ii+numoutput];// phase is stored here
00793               OUTPUT[ii] *= (150./meanmag);// scaled mag now has mean==150
00794               if      (OUTPUT[ii]<16)  OUTPUT[ii]=16;
00795               else if (OUTPUT[ii]>255) OUTPUT[ii]=255;
00796               }
00797             uchar *OUT_UC_MAG;                          // temp store for mag.
00798             OUT_UC_MAG = new uchar[numoutput];
00799             rescale(OUT_UC_MAG,OUTPUT,numoutput,0,255,0,15);   // fill ucmag with mag
00800             rescale(OUT_UC,OUT_PHA,numoutput,-PI,PI,0,15);     // fill uc with phase
00801             // ______ transform data=16*mag+pha ______
00802             for (int ii=0; ii<numoutput; ++ii)
00803               OUT_UC[ii] += 16*OUT_UC_MAG[ii];//        e[0:255]
00804             // ______ Add scalebar if requested ______
00805             // ______ by changing the data in lower right corner ______
00806             if (input.scalebar)
00807               {
00808               if (outputlinecnt>=line0scalebar && outputlinecnt<=lineNscalebar)
00809                 {
00810                 // ______ change the data to [0:255] ______
00811                 for (int ii=pixel0scalebar; ii<=pixel0scalebar+scalebarwidth; ++ii)
00812                   {
00813                   OUT_UC[ii]= uchar(240+(float(ii-pixel0scalebar)*
00814                                     (16./float(scalebarwidth))));
00815                   }
00816                 }
00817               }
00818             break; // switch
00819             }
00820           default:
00821             cerr << "unknown option with sunraster output, uc1, assuming phase\n";
00822             rescale(OUT_UC,OUTPUT,numoutput,-PI,PI,0,255);          // fill uc
00823           }
00824         cout.write((char*)&OUT_UC[0],numoutput*sizeoutput); // binary to stdout
00825         break;
00826         }
00827       default:
00828         cerr << "PANIC: Impossible no oformat...\n";
00829       } // switch output format, write per output line
00830 
00831     // ______ Write some extra req. at end of line ______
00832     if (input.oformat==ASCII) cout << endl;
00833 
00834     // ______ Write extra zero after each line if odd width ______
00835     // ______ It seems format requires even width? (at least xv does) ______
00836     if (input.oformat==SUNRASTER)
00837       {
00838       if ((numoutput%2)!=0) // originally odd
00839         {
00840         // ______ Header and colormap already written ______
00841         // ______ But write extra 0 at end??? (why... bk) 
00842         // ______ This seems to be req. for xv?
00843         uchar sameaslast;
00844         rescale(&sameaslast,&OUTPUT[numoutput-1],1,-PI,PI,0,255);
00845         cout.write((char*)&sameaslast,1);
00846         }
00847       }
00848 
00849     } // loop over lines
00850 
00851   if (giveprogress==true) cerr << endl;
00852   } // END function
00853 
00854 
00855 
00856 /****************************************************************
00857  * rescale                                                      *
00858  * rescale data in IN(min,max) --> out[MIN,MAX]                 *
00859  * o(x) = (i(x)-min) * (newrange/oldrange) + newmin             *
00860  #%// BK 17-Nov-2000                                            *
00861  ****************************************************************/
00862 void rescale(
00863         uchar *OUT,
00864         float *IN,
00865         const int numin,
00866         const float MIN,
00867         const float MAX,
00868         const float NEWMIN,
00869         const float NEWMAX)
00870   {
00871   if (MIN>MAX)
00872     {
00873     cerr << "wrong input in recale: min>max\n";
00874     exit (1);
00875     }
00876   if (NEWMIN>NEWMAX)
00877     {
00878     cerr << "wrong input in recale: newmin>newmax\n";
00879     exit (1);
00880     }
00881   if (NEWMIN<0 || NEWMAX>255)
00882     {
00883     cerr << "wrong input in recale: newmin<0 or newmax>255\n";
00884     exit (1);
00885     }
00886   //const float NEWMIN   = 0.;
00887   //const float NEWMAX   = 255.;
00888   const float NEWRANGE = NEWMAX-NEWMIN;
00889   const float RANGE    = MAX-MIN;
00890   const float SCALE    = NEWRANGE/RANGE;
00891   for (int ii=0; ii<numin; ++ii)
00892     {
00893     //if      (IN[ii]<MIN) OUT[ii]=uchar(NEWMIN);// avoid clipping
00894     //else if (IN[ii]>MAX) OUT[ii]=uchar(NEWMAX);// avoid clipping
00895     //else OUT[ii] = uchar(NEWMIN + (((IN[ii])-MIN) * SCALE));
00896     OUT[ii] = uchar(NEWMIN + (((IN[ii])-MIN) * SCALE));
00897     }
00898   } // END rescale
00899 
00900 
00901 
00902 /****************************************************************
00903  * rasterheader                                                 *
00904  * or save as gif/jpg/bmp/tiff/etc?                             * 
00905  *                                                              *
00906  * ***** SUNraster header defined as 8 integers:                *
00907  * ras_magic:     [0x59a66a95] magic number                     *
00908  * ras_width:     [input]      width (pixels) of image          *
00909  * ras_height:    [input]      height (pixels) of image         *
00910  * ras_depth:     [8]          depth (1, 8, or 24 bits)         *
00911  * ras_length:    [computed]   length (bytes) of image          *
00912  * ras_type:      [1]          file; see RT_* below             *
00913  * ras_maptype:   [1]          colormap; see RMT_* below        *
00914  * ras_maplength: [3*256]      length (b) of following map      *
00915  *                                                              *
00916  * ***** Sun supported ras_type's RT_ ***                       *
00917  * 0       Raw pixrect image in 68000 byte order                *
00918  * 1       Raw pixrect image in 68000 byte order                *
00919  * 2       Run-length compression of bytes                      *
00920  * 3       XRGB or RGB instead of XBGR or BGR                   *
00921  * 4       tiff <-> standard rasterfile                         *
00922  * 5       iff (TAAC format) <-> standard rasterfile            *
00923  * 0xffff  Reserved for testing                                 *
00924  *                                                              *
00925  * ***** Sun registered ras_maptype's RMT_ ***                  *
00926  * 0       ras_maplength is expected to be 0                    *
00927  * 1       red[ras_maplength/3],green[],blue[]                  *
00928  * 2       RMT_RAW                                              *
00929  *                                                              *
00930  * It seems width must be even? (fix this)                      *
00931  #%// BK 17-Nov-2000                                            *
00932  ****************************************************************/
00933 void rasterheader(unsigned long HEADER[8], const int width, const int height)
00934   {
00935   // ______ if not even width, make it even, and write last uchar twice ______
00936   const int W = ((width%2)==0) ? width : width+1;
00937   HEADER[0] = htonl(0x59a66a95);    // magic number, always same
00938   HEADER[1] = htonl(W);             // #columns, force even width
00939   HEADER[2] = htonl(height);        // #rows
00940   HEADER[3] = htonl(8);             // #planes in bits
00941   HEADER[4] = htonl(W*height);      // size in bytes
00942   HEADER[5] = htonl(1);             // rect type
00943   HEADER[6] = htonl(1);             // RMT_RGB follows, size = H[7]
00944   HEADER[7] = htonl(3*256);         // rgb, foreach possible pixelvalue
00945   } // END rasterheader
00946 
00947 
00948 /****************************************************************
00949  * makecmap                                                     *
00950  * input option -c: only for sunraster output:                  *
00951  * generate a cmap from a input file, or from a name "gray", ?  *
00952  * input file consist of 256 ascii entries r g b                *
00953  #%// BK 22-Nov-2000                                            *
00954  ****************************************************************/
00955 void makecmap(
00956         unsigned char CMAP[3][256],
00957         const commandlineinput &input)
00958   {
00959   const int maplength = 256;                    // always
00960   if (input.oformat!=SUNRASTER)
00961     {
00962     cerr << "makecmap: oformat != sunraster.\n";
00963     exit(1);
00964     }
00965 
00966   // ______ Start internal maps, length 256 ______
00967   if (!strcmp(input.cmap,"gray"))
00968     {
00969     for (int color=0; color<3; ++color)
00970       {
00971       for (int ii=0; ii<maplength; ++ii)
00972         {
00973         CMAP[0][ii] = uchar(ii*256/maplength);  // red
00974         CMAP[1][ii] = uchar(ii*256/maplength);  // green
00975         CMAP[2][ii] = uchar(ii*256/maplength);  // blue
00976         }
00977       }
00978     }
00979 
00980   else if (!strcmp(input.cmap,"bert"))  // i.e. random for testing
00981     {
00982     for (int color=0; color<3; ++color)
00983       for (int ii=0; ii<maplength; ++ii)
00984         CMAP[color][ii] = uchar((color+1)*ii);  // rgb
00985     }
00986 
00987   else if (!strcmp(input.cmap,"jet"))
00988     {
00989     const double m = maplength-1;                               // 255
00990     const double n = floor(((m+1)/4)+0.5);
00991     double k       = 0.;
00992     for (int ii=0; ii<int(0.5*n); ++ii)
00993       {
00994       k++;
00995       double y    = (k+n/2)/n;
00996       CMAP[0][ii] = uchar(0);
00997       CMAP[1][ii] = uchar(0);
00998       CMAP[2][ii] = uchar(m*y);
00999       }
01000     k = 0.;
01001     for (int ii=int(0.5*n); ii<int(1.5*n); ++ii)
01002       {
01003       k++;
01004       double x    = k/n;
01005       CMAP[0][ii] = uchar(0);
01006       CMAP[1][ii] = uchar(m*x);
01007       CMAP[2][ii] = uchar(m);
01008       }
01009     k = 0.;
01010     double k2 = n;
01011     for (int ii=int(1.5*n); ii<int(2.5*n); ++ii)
01012       {
01013       k++;
01014       double x    = k/n;
01015       double x2   = k2/n;
01016       CMAP[0][ii] = uchar(m*x);
01017       CMAP[1][ii] = uchar(m);
01018       CMAP[2][ii] = uchar(m*x2);
01019       k2--;
01020       }
01021     k2 = n;
01022     for (int ii=int(2.5*n); ii<int(3.5*n); ++ii)
01023       {
01024       double x2   = k2/n;
01025       CMAP[0][ii] = uchar(m);
01026       CMAP[1][ii] = uchar(m*x2);
01027       CMAP[2][ii] = uchar(0);
01028       k2--;
01029       }
01030     k2 = n;
01031     for (int ii=int(3.5*n); ii<maplength; ++ii)
01032       {
01033       double y2   = (k2+n/2)/n;
01034       CMAP[0][ii] = uchar(m*y2);
01035       CMAP[1][ii] = uchar(0);
01036       CMAP[2][ii] = uchar(0);
01037       k2--;
01038       }
01039     } // jet
01040 
01041   else if (!strcmp(input.cmap,"cool"))
01042     {
01043     const double m = maplength-1;               // 255
01044     for (int ii=0; ii<maplength; ++ii)
01045       {
01046       CMAP[0][ii] = uchar(ii);                  // r
01047       CMAP[1][ii] = uchar(m-ii);                // g
01048       CMAP[2][ii] = uchar(m);                   // b
01049       }
01050     } // hot
01051 
01052   else if (!strcmp(input.cmap,"hot"))
01053     {
01054     const double m = maplength-1;                               // 255
01055     const double n = int(m*(3./8.));
01056     for (int ii=0; ii<=int(m); ++ii)
01057       {
01058       CMAP[0][ii] = (ii<n) ? uchar(m*ii/n):uchar(m);            // r
01059       if      (ii<n)   CMAP[1][ii] = uchar(0);                  // g
01060       else if (ii<2*n) CMAP[1][ii] = uchar(m*((ii-n)/n));       // g
01061       else             CMAP[1][ii] = uchar(m);                  // g
01062       CMAP[2][ii] = (ii<2*n) ? uchar(0):uchar(m*((ii-2*n)/(m-2*n)));  // b
01063       }
01064     } // hot
01065 
01066   else if (!strcmp(input.cmap,"hsv"))
01067     // ______ Created with matlab ph(256)*256, code with awk BK 04-Apr-2001 ______
01068     // >> map=round(255*ph(256));
01069     // >> fid=fopen('map.txt','w'); 
01070     // >> for ii=1:256
01071     // fprintf(fid,'%i %i %i\n',map(ii,:));
01072     // end
01073     // >> fclose(fid);
01074     // awk '{i++;print "CMAP[0]["i-1"]="$1";", "CMAP[1]["i-1"]="$2";",
01075     // "CMAP[2]["i-1"]="$3";"}' map.txt > map.code
01076     // vi: ":r map.code"
01077     // (spaces in vi: mark start with mb, end with me, then substitute
01078     // start of lnie with 4 spaces: ":'b,'e s/^/    /"
01079     {
01080     CMAP[0][0]=102; CMAP[1][0]=255; CMAP[2][0]=255;
01081     CMAP[0][1]=104; CMAP[1][1]=251; CMAP[2][1]=255;
01082     CMAP[0][2]=105; CMAP[1][2]=248; CMAP[2][2]=255;
01083     CMAP[0][3]=107; CMAP[1][3]=244; CMAP[2][3]=255;
01084     CMAP[0][4]=108; CMAP[1][4]=241; CMAP[2][4]=255;
01085     CMAP[0][5]=110; CMAP[1][5]=238; CMAP[2][5]=255;
01086     CMAP[0][6]=111; CMAP[1][6]=235; CMAP[2][6]=255;
01087     CMAP[0][7]=113; CMAP[1][7]=231; CMAP[2][7]=255;
01088     CMAP[0][8]=114; CMAP[1][8]=228; CMAP[2][8]=255;
01089     CMAP[0][9]=116; CMAP[1][9]=225; CMAP[2][9]=255;
01090     CMAP[0][10]=117; CMAP[1][10]=222; CMAP[2][10]=255;
01091     CMAP[0][11]=119; CMAP[1][11]=220; CMAP[2][11]=255;
01092     CMAP[0][12]=120; CMAP[1][12]=217; CMAP[2][12]=255;
01093     CMAP[0][13]=122; CMAP[1][13]=214; CMAP[2][13]=255;
01094     CMAP[0][14]=123; CMAP[1][14]=211; CMAP[2][14]=255;
01095     CMAP[0][15]=125; CMAP[1][15]=209; CMAP[2][15]=255;
01096     CMAP[0][16]=126; CMAP[1][16]=206; CMAP[2][16]=255;
01097     CMAP[0][17]=128; CMAP[1][17]=204; CMAP[2][17]=255;
01098     CMAP[0][18]=129; CMAP[1][18]=201; CMAP[2][18]=255;
01099     CMAP[0][19]=131; CMAP[1][19]=199; CMAP[2][19]=255;
01100     CMAP[0][20]=132; CMAP[1][20]=197; CMAP[2][20]=255;
01101     CMAP[0][21]=134; CMAP[1][21]=195; CMAP[2][21]=255;
01102     CMAP[0][22]=135; CMAP[1][22]=193; CMAP[2][22]=255;
01103     CMAP[0][23]=137; CMAP[1][23]=191; CMAP[2][23]=255;
01104     CMAP[0][24]=138; CMAP[1][24]=189; CMAP[2][24]=255;
01105     CMAP[0][25]=140; CMAP[1][25]=187; CMAP[2][25]=255;
01106     CMAP[0][26]=141; CMAP[1][26]=185; CMAP[2][26]=255;
01107     CMAP[0][27]=143; CMAP[1][27]=183; CMAP[2][27]=255;
01108     CMAP[0][28]=144; CMAP[1][28]=182; CMAP[2][28]=255;
01109     CMAP[0][29]=146; CMAP[1][29]=180; CMAP[2][29]=255;
01110     CMAP[0][30]=147; CMAP[1][30]=178; CMAP[2][30]=255;
01111     CMAP[0][31]=149; CMAP[1][31]=177; CMAP[2][31]=255;
01112     CMAP[0][32]=150; CMAP[1][32]=176; CMAP[2][32]=255;
01113     CMAP[0][33]=152; CMAP[1][33]=174; CMAP[2][33]=255;
01114     CMAP[0][34]=153; CMAP[1][34]=173; CMAP[2][34]=255;
01115     CMAP[0][35]=155; CMAP[1][35]=172; CMAP[2][35]=255;
01116     CMAP[0][36]=156; CMAP[1][36]=171; CMAP[2][36]=255;
01117     CMAP[0][37]=158; CMAP[1][37]=170; CMAP[2][37]=255;
01118     CMAP[0][38]=159; CMAP[1][38]=169; CMAP[2][38]=255;
01119     CMAP[0][39]=161; CMAP[1][39]=168; CMAP[2][39]=255;
01120     CMAP[0][40]=162; CMAP[1][40]=167; CMAP[2][40]=255;
01121     CMAP[0][41]=164; CMAP[1][41]=166; CMAP[2][41]=255;
01122     CMAP[0][42]=165; CMAP[1][42]=166; CMAP[2][42]=255;
01123     CMAP[0][43]=166; CMAP[1][43]=165; CMAP[2][43]=255;
01124     CMAP[0][44]=167; CMAP[1][44]=164; CMAP[2][44]=255;
01125     CMAP[0][45]=168; CMAP[1][45]=162; CMAP[2][45]=255;
01126     CMAP[0][46]=169; CMAP[1][46]=161; CMAP[2][46]=255;
01127     CMAP[0][47]=170; CMAP[1][47]=159; CMAP[2][47]=255;
01128     CMAP[0][48]=171; CMAP[1][48]=158; CMAP[2][48]=255;
01129     CMAP[0][49]=172; CMAP[1][49]=156; CMAP[2][49]=255;
01130     CMAP[0][50]=173; CMAP[1][50]=155; CMAP[2][50]=255;
01131     CMAP[0][51]=174; CMAP[1][51]=153; CMAP[2][51]=255;
01132     CMAP[0][52]=175; CMAP[1][52]=152; CMAP[2][52]=255;
01133     CMAP[0][53]=176; CMAP[1][53]=150; CMAP[2][53]=255;
01134     CMAP[0][54]=178; CMAP[1][54]=149; CMAP[2][54]=255;
01135     CMAP[0][55]=179; CMAP[1][55]=147; CMAP[2][55]=255;
01136     CMAP[0][56]=181; CMAP[1][56]=146; CMAP[2][56]=255;
01137     CMAP[0][57]=182; CMAP[1][57]=144; CMAP[2][57]=255;
01138     CMAP[0][58]=184; CMAP[1][58]=143; CMAP[2][58]=255;
01139     CMAP[0][59]=186; CMAP[1][59]=141; CMAP[2][59]=255;
01140     CMAP[0][60]=188; CMAP[1][60]=140; CMAP[2][60]=255;
01141     CMAP[0][61]=190; CMAP[1][61]=138; CMAP[2][61]=255;
01142     CMAP[0][62]=192; CMAP[1][62]=137; CMAP[2][62]=255;
01143     CMAP[0][63]=194; CMAP[1][63]=135; CMAP[2][63]=255;
01144     CMAP[0][64]=196; CMAP[1][64]=134; CMAP[2][64]=255;
01145     CMAP[0][65]=198; CMAP[1][65]=132; CMAP[2][65]=255;
01146     CMAP[0][66]=200; CMAP[1][66]=131; CMAP[2][66]=255;
01147     CMAP[0][67]=202; CMAP[1][67]=129; CMAP[2][67]=255;
01148     CMAP[0][68]=205; CMAP[1][68]=128; CMAP[2][68]=255;
01149     CMAP[0][69]=207; CMAP[1][69]=126; CMAP[2][69]=255;
01150     CMAP[0][70]=210; CMAP[1][70]=124; CMAP[2][70]=255;
01151     CMAP[0][71]=212; CMAP[1][71]=123; CMAP[2][71]=255;
01152     CMAP[0][72]=215; CMAP[1][72]=122; CMAP[2][72]=255;
01153     CMAP[0][73]=218; CMAP[1][73]=120; CMAP[2][73]=255;
01154     CMAP[0][74]=221; CMAP[1][74]=119; CMAP[2][74]=255;
01155     CMAP[0][75]=223; CMAP[1][75]=117; CMAP[2][75]=255;
01156     CMAP[0][76]=226; CMAP[1][76]=116; CMAP[2][76]=255;
01157     CMAP[0][77]=229; CMAP[1][77]=114; CMAP[2][77]=255;
01158     CMAP[0][78]=233; CMAP[1][78]=113; CMAP[2][78]=255;
01159     CMAP[0][79]=236; CMAP[1][79]=111; CMAP[2][79]=255;
01160     CMAP[0][80]=239; CMAP[1][80]=110; CMAP[2][80]=255;
01161     CMAP[0][81]=242; CMAP[1][81]=108; CMAP[2][81]=255;
01162     CMAP[0][82]=246; CMAP[1][82]=106; CMAP[2][82]=255;
01163     CMAP[0][83]=249; CMAP[1][83]=105; CMAP[2][83]=255;
01164     CMAP[0][84]=253; CMAP[1][84]=104; CMAP[2][84]=255;
01165     CMAP[0][85]=255; CMAP[1][85]=102; CMAP[2][85]=254;
01166     CMAP[0][86]=255; CMAP[1][86]=104; CMAP[2][86]=250;
01167     CMAP[0][87]=255; CMAP[1][87]=105; CMAP[2][87]=247;
01168     CMAP[0][88]=255; CMAP[1][88]=106; CMAP[2][88]=243;
01169     CMAP[0][89]=255; CMAP[1][89]=108; CMAP[2][89]=240;
01170     CMAP[0][90]=255; CMAP[1][90]=110; CMAP[2][90]=237;
01171     CMAP[0][91]=255; CMAP[1][91]=111; CMAP[2][91]=233;
01172     CMAP[0][92]=255; CMAP[1][92]=113; CMAP[2][92]=230;
01173     CMAP[0][93]=255; CMAP[1][93]=114; CMAP[2][93]=227;
01174     CMAP[0][94]=255; CMAP[1][94]=116; CMAP[2][94]=224;
01175     CMAP[0][95]=255; CMAP[1][95]=117; CMAP[2][95]=221;
01176     CMAP[0][96]=255; CMAP[1][96]=119; CMAP[2][96]=218;
01177     CMAP[0][97]=255; CMAP[1][97]=120; CMAP[2][97]=216;
01178     CMAP[0][98]=255; CMAP[1][98]=122; CMAP[2][98]=213;
01179     CMAP[0][99]=255; CMAP[1][99]=123; CMAP[2][99]=210;
01180     CMAP[0][100]=255; CMAP[1][100]=125; CMAP[2][100]=208;
01181     CMAP[0][101]=255; CMAP[1][101]=126; CMAP[2][101]=205;
01182     CMAP[0][102]=255; CMAP[1][102]=128; CMAP[2][102]=203;
01183     CMAP[0][103]=255; CMAP[1][103]=129; CMAP[2][103]=200;
01184     CMAP[0][104]=255; CMAP[1][104]=131; CMAP[2][104]=198;
01185     CMAP[0][105]=255; CMAP[1][105]=132; CMAP[2][105]=196;
01186     CMAP[0][106]=255; CMAP[1][106]=134; CMAP[2][106]=194;
01187     CMAP[0][107]=255; CMAP[1][107]=135; CMAP[2][107]=192;
01188     CMAP[0][108]=255; CMAP[1][108]=137; CMAP[2][108]=190;
01189     CMAP[0][109]=255; CMAP[1][109]=138; CMAP[2][109]=188;
01190     CMAP[0][110]=255; CMAP[1][110]=140; CMAP[2][110]=186;
01191     CMAP[0][111]=255; CMAP[1][111]=141; CMAP[2][111]=184;
01192     CMAP[0][112]=255; CMAP[1][112]=143; CMAP[2][112]=182;
01193     CMAP[0][113]=255; CMAP[1][113]=144; CMAP[2][113]=181;
01194     CMAP[0][114]=255; CMAP[1][114]=146; CMAP[2][114]=179;
01195     CMAP[0][115]=255; CMAP[1][115]=147; CMAP[2][115]=178;
01196     CMAP[0][116]=255; CMAP[1][116]=149; CMAP[2][116]=176;
01197     CMAP[0][117]=255; CMAP[1][117]=150; CMAP[2][117]=175;
01198     CMAP[0][118]=255; CMAP[1][118]=152; CMAP[2][118]=174;
01199     CMAP[0][119]=255; CMAP[1][119]=153; CMAP[2][119]=172;
01200     CMAP[0][120]=255; CMAP[1][120]=155; CMAP[2][120]=171;
01201     CMAP[0][121]=255; CMAP[1][121]=156; CMAP[2][121]=170;
01202     CMAP[0][122]=255; CMAP[1][122]=158; CMAP[2][122]=169;
01203     CMAP[0][123]=255; CMAP[1][123]=159; CMAP[2][123]=168;
01204     CMAP[0][124]=255; CMAP[1][124]=161; CMAP[2][124]=167;
01205     CMAP[0][125]=255; CMAP[1][125]=162; CMAP[2][125]=166;
01206     CMAP[0][126]=255; CMAP[1][126]=164; CMAP[2][126]=166;
01207     CMAP[0][127]=255; CMAP[1][127]=165; CMAP[2][127]=165;
01208     CMAP[0][128]=255; CMAP[1][128]=165; CMAP[2][128]=165;
01209     CMAP[0][129]=255; CMAP[1][129]=166; CMAP[2][129]=164;
01210     CMAP[0][130]=255; CMAP[1][130]=166; CMAP[2][130]=162;
01211     CMAP[0][131]=255; CMAP[1][131]=167; CMAP[2][131]=161;
01212     CMAP[0][132]=255; CMAP[1][132]=168; CMAP[2][132]=159;
01213     CMAP[0][133]=255; CMAP[1][133]=169; CMAP[2][133]=157;
01214     CMAP[0][134]=255; CMAP[1][134]=170; CMAP[2][134]=156;
01215     CMAP[0][135]=255; CMAP[1][135]=171; CMAP[2][135]=155;
01216     CMAP[0][136]=255; CMAP[1][136]=172; CMAP[2][136]=153;
01217     CMAP[0][137]=255; CMAP[1][137]=174; CMAP[2][137]=152;
01218     CMAP[0][138]=255; CMAP[1][138]=175; CMAP[2][138]=150;
01219     CMAP[0][139]=255; CMAP[1][139]=176; CMAP[2][139]=149;
01220     CMAP[0][140]=255; CMAP[1][140]=178; CMAP[2][140]=147;
01221     CMAP[0][141]=255; CMAP[1][141]=179; CMAP[2][141]=145;
01222     CMAP[0][142]=255; CMAP[1][142]=181; CMAP[2][142]=144;
01223     CMAP[0][143]=255; CMAP[1][143]=182; CMAP[2][143]=142;
01224     CMAP[0][144]=255; CMAP[1][144]=184; CMAP[2][144]=141;
01225     CMAP[0][145]=255; CMAP[1][145]=186; CMAP[2][145]=139;
01226     CMAP[0][146]=255; CMAP[1][146]=188; CMAP[2][146]=138;
01227     CMAP[0][147]=255; CMAP[1][147]=190; CMAP[2][147]=137;
01228     CMAP[0][148]=255; CMAP[1][148]=192; CMAP[2][148]=135;
01229     CMAP[0][149]=255; CMAP[1][149]=194; CMAP[2][149]=134;
01230     CMAP[0][150]=255; CMAP[1][150]=196; CMAP[2][150]=132;
01231     CMAP[0][151]=255; CMAP[1][151]=198; CMAP[2][151]=131;
01232     CMAP[0][152]=255; CMAP[1][152]=200; CMAP[2][152]=129;
01233     CMAP[0][153]=255; CMAP[1][153]=203; CMAP[2][153]=128;
01234     CMAP[0][154]=255; CMAP[1][154]=205; CMAP[2][154]=126;
01235     CMAP[0][155]=255; CMAP[1][155]=208; CMAP[2][155]=125;
01236     CMAP[0][156]=255; CMAP[1][156]=210; CMAP[2][156]=123;
01237     CMAP[0][157]=255; CMAP[1][157]=213; CMAP[2][157]=122;
01238     CMAP[0][158]=255; CMAP[1][158]=216; CMAP[2][158]=120;
01239     CMAP[0][159]=255; CMAP[1][159]=218; CMAP[2][159]=119;
01240     CMAP[0][160]=255; CMAP[1][160]=221; CMAP[2][160]=117;
01241     CMAP[0][161]=255; CMAP[1][161]=224; CMAP[2][161]=116;
01242     CMAP[0][162]=255; CMAP[1][162]=227; CMAP[2][162]=114;
01243     CMAP[0][163]=255; CMAP[1][163]=230; CMAP[2][163]=113;
01244     CMAP[0][164]=255; CMAP[1][164]=233; CMAP[2][164]=111;
01245     CMAP[0][165]=255; CMAP[1][165]=237; CMAP[2][165]=109;
01246     CMAP[0][166]=255; CMAP[1][166]=240; CMAP[2][166]=108;
01247     CMAP[0][167]=255; CMAP[1][167]=243; CMAP[2][167]=106;
01248     CMAP[0][168]=255; CMAP[1][168]=247; CMAP[2][168]=105;
01249     CMAP[0][169]=255; CMAP[1][169]=250; CMAP[2][169]=104;
01250     CMAP[0][170]=255; CMAP[1][170]=254; CMAP[2][170]=102;
01251     CMAP[0][171]=253; CMAP[1][171]=255; CMAP[2][171]=104;
01252     CMAP[0][172]=249; CMAP[1][172]=255; CMAP[2][172]=105;
01253     CMAP[0][173]=246; CMAP[1][173]=255; CMAP[2][173]=106;
01254     CMAP[0][174]=242; CMAP[1][174]=255; CMAP[2][174]=108;
01255     CMAP[0][175]=239; CMAP[1][175]=255; CMAP[2][175]=109;
01256     CMAP[0][176]=236; CMAP[1][176]=255; CMAP[2][176]=111;
01257     CMAP[0][177]=233; CMAP[1][177]=255; CMAP[2][177]=112;
01258     CMAP[0][178]=229; CMAP[1][178]=255; CMAP[2][178]=114;
01259     CMAP[0][179]=226; CMAP[1][179]=255; CMAP[2][179]=115;
01260     CMAP[0][180]=223; CMAP[1][180]=255; CMAP[2][180]=117;
01261     CMAP[0][181]=221; CMAP[1][181]=255; CMAP[2][181]=119;
01262     CMAP[0][182]=218; CMAP[1][182]=255; CMAP[2][182]=120;
01263     CMAP[0][183]=215; CMAP[1][183]=255; CMAP[2][183]=122;
01264     CMAP[0][184]=212; CMAP[1][184]=255; CMAP[2][184]=123;
01265     CMAP[0][185]=210; CMAP[1][185]=255; CMAP[2][185]=124;
01266     CMAP[0][186]=207; CMAP[1][186]=255; CMAP[2][186]=126;
01267     CMAP[0][187]=205; CMAP[1][187]=255; CMAP[2][187]=127;
01268     CMAP[0][188]=202; CMAP[1][188]=255; CMAP[2][188]=129;
01269     CMAP[0][189]=200; CMAP[1][189]=255; CMAP[2][189]=131;
01270     CMAP[0][190]=198; CMAP[1][190]=255; CMAP[2][190]=132;
01271     CMAP[0][191]=196; CMAP[1][191]=255; CMAP[2][191]=134;
01272     CMAP[0][192]=194; CMAP[1][192]=255; CMAP[2][192]=135;
01273     CMAP[0][193]=192; CMAP[1][193]=255; CMAP[2][193]=137;
01274     CMAP[0][194]=190; CMAP[1][194]=255; CMAP[2][194]=138;
01275     CMAP[0][195]=188; CMAP[1][195]=255; CMAP[2][195]=139;
01276     CMAP[0][196]=186; CMAP[1][196]=255; CMAP[2][196]=141;
01277     CMAP[0][197]=184; CMAP[1][197]=255; CMAP[2][197]=143;
01278     CMAP[0][198]=182; CMAP[1][198]=255; CMAP[2][198]=144;
01279     CMAP[0][199]=181; CMAP[1][199]=255; CMAP[2][199]=146;
01280     CMAP[0][200]=179; CMAP[1][200]=255; CMAP[2][200]=147;
01281     CMAP[0][201]=178; CMAP[1][201]=255; CMAP[2][201]=149;
01282     CMAP[0][202]=176; CMAP[1][202]=255; CMAP[2][202]=150;
01283     CMAP[0][203]=175; CMAP[1][203]=255; CMAP[2][203]=152;
01284     CMAP[0][204]=174; CMAP[1][204]=255; CMAP[2][204]=153;
01285     CMAP[0][205]=173; CMAP[1][205]=255; CMAP[2][205]=155;
01286     CMAP[0][206]=172; CMAP[1][206]=255; CMAP[2][206]=156;
01287     CMAP[0][207]=171; CMAP[1][207]=255; CMAP[2][207]=158;
01288     CMAP[0][208]=170; CMAP[1][208]=255; CMAP[2][208]=159;
01289     CMAP[0][209]=169; CMAP[1][209]=255; CMAP[2][209]=161;
01290     CMAP[0][210]=168; CMAP[1][210]=255; CMAP[2][210]=162;
01291     CMAP[0][211]=167; CMAP[1][211]=255; CMAP[2][211]=164;
01292     CMAP[0][212]=166; CMAP[1][212]=255; CMAP[2][212]=165;
01293     CMAP[0][213]=165; CMAP[1][213]=255; CMAP[2][213]=166;
01294     CMAP[0][214]=164; CMAP[1][214]=255; CMAP[2][214]=166;
01295     CMAP[0][215]=162; CMAP[1][215]=255; CMAP[2][215]=167;
01296     CMAP[0][216]=161; CMAP[1][216]=255; CMAP[2][216]=168;
01297     CMAP[0][217]=159; CMAP[1][217]=255; CMAP[2][217]=169;
01298     CMAP[0][218]=158; CMAP[1][218]=255; CMAP[2][218]=170;
01299     CMAP[0][219]=156; CMAP[1][219]=255; CMAP[2][219]=171;
01300     CMAP[0][220]=155; CMAP[1][220]=255; CMAP[2][220]=172;
01301     CMAP[0][221]=153; CMAP[1][221]=255; CMAP[2][221]=173;
01302     CMAP[0][222]=152; CMAP[1][222]=255; CMAP[2][222]=174;
01303     CMAP[0][223]=150; CMAP[1][223]=255; CMAP[2][223]=176;
01304     CMAP[0][224]=149; CMAP[1][224]=255; CMAP[2][224]=177;
01305     CMAP[0][225]=147; CMAP[1][225]=255; CMAP[2][225]=178;
01306     CMAP[0][226]=146; CMAP[1][226]=255; CMAP[2][226]=180;
01307     CMAP[0][227]=144; CMAP[1][227]=255; CMAP[2][227]=182;
01308     CMAP[0][228]=142; CMAP[1][228]=255; CMAP[2][228]=183;
01309     CMAP[0][229]=141; CMAP[1][229]=255; CMAP[2][229]=185;
01310     CMAP[0][230]=139; CMAP[1][230]=255; CMAP[2][230]=187;
01311     CMAP[0][231]=138; CMAP[1][231]=255; CMAP[2][231]=189;
01312     CMAP[0][232]=137; CMAP[1][232]=255; CMAP[2][232]=191;
01313     CMAP[0][233]=135; CMAP[1][233]=255; CMAP[2][233]=193;
01314     CMAP[0][234]=134; CMAP[1][234]=255; CMAP[2][234]=195;
01315     CMAP[0][235]=132; CMAP[1][235]=255; CMAP[2][235]=197;
01316     CMAP[0][236]=131; CMAP[1][236]=255; CMAP[2][236]=199;
01317     CMAP[0][237]=129; CMAP[1][237]=255; CMAP[2][237]=201;
01318     CMAP[0][238]=128; CMAP[1][238]=255; CMAP[2][238]=204;
01319     CMAP[0][239]=126; CMAP[1][239]=255; CMAP[2][239]=206;
01320     CMAP[0][240]=125; CMAP[1][240]=255; CMAP[2][240]=209;
01321     CMAP[0][241]=123; CMAP[1][241]=255; CMAP[2][241]=211;
01322     CMAP[0][242]=122; CMAP[1][242]=255; CMAP[2][242]=214;
01323     CMAP[0][243]=120; CMAP[1][243]=255; CMAP[2][243]=217;
01324     CMAP[0][244]=119; CMAP[1][244]=255; CMAP[2][244]=220;
01325     CMAP[0][245]=117; CMAP[1][245]=255; CMAP[2][245]=222;
01326     CMAP[0][246]=116; CMAP[1][246]=255; CMAP[2][246]=225;
01327     CMAP[0][247]=114; CMAP[1][247]=255; CMAP[2][247]=228;
01328     CMAP[0][248]=113; CMAP[1][248]=255; CMAP[2][248]=231;
01329     CMAP[0][249]=111; CMAP[1][249]=255; CMAP[2][249]=235;
01330     CMAP[0][250]=110; CMAP[1][250]=255; CMAP[2][250]=238;
01331     CMAP[0][251]=108; CMAP[1][251]=255; CMAP[2][251]=241;
01332     CMAP[0][252]=106; CMAP[1][252]=255; CMAP[2][252]=244;
01333     CMAP[0][253]=105; CMAP[1][253]=255; CMAP[2][253]=248;
01334     CMAP[0][254]=104; CMAP[1][254]=255; CMAP[2][254]=251;
01335     CMAP[0][255]=102; CMAP[1][255]=255; CMAP[2][255]=255;
01336     }
01337 
01338   else // load from ascii file, generated by, e.g., makecpt
01339        //  line1: r g b  (e.g. 255 0 255)
01340        //  line2: r g b  (e.g. 255 0 240)
01341        //  ...    ...
01342     {
01343     //ifstream cmap(input.cmap, ios::in | ios::nocreate);
01344     ifstream cmap(input.cmap, ios::in);
01345     if (!cmap) 
01346       {
01347       cerr << "cpxfiddle: ERROR: Could not open colormap file: " << input.cmap << "\n";
01348       exit(1);
01349       }
01350     char dummyline[128];
01351     int value;
01352     for (int ii=0; ii<maplength; ++ii)
01353       {
01354       for (int color=0; color<3; ++color)
01355         {
01356         cmap >> value;
01357         CMAP[color][ii] = uchar(value);
01358         }
01359       cmap.getline(dummyline,128,'\n');
01360       }
01361     cmap.close();
01362     }
01363 
01364   // ______ Display colormap for testing ______
01365   if (input.verbose==true)
01366     {
01367     #define VERBOSE
01368     #ifdef VERBOSE
01369     cerr << "Color table for SUNraster (rgb):\n";
01370     for (int ii=0; ii<maplength; ++ii)
01371       cerr << int(CMAP[0][ii]) << " "
01372            << int(CMAP[1][ii]) << " "
01373            << int(CMAP[2][ii]) << "\n";
01374     #endif
01375     }
01376   } // END makecmap
01377 
01378 
01379 /****************************************************************
01380  * makecmapmixed                                                *
01381  * input option -c: only for sunraster output:                  *
01382  * generate a cmap from a input file, or from a name "gray", ?  *
01383  * input file consist of 256 ascii entries r g b                *
01384  * This function creates a mixed colormap, so that data that is *
01385  * d = numcolorsphase*mag + phase                               *
01386  * is displayed as overlay phase over mag.                      *
01387  * This function uses makecmap to generate a map of length 256  *
01388  * that is composed of 16 repeated colormap for phase with      *
01389  * different brightness levels.                                 *
01390  #%// BK 04-Apr-2001                                            *
01391  ****************************************************************/
01392 void makecmapmixed(
01393         unsigned char CMAP[3][256],
01394         const commandlineinput &input)
01395   {
01396   // do not change!
01397   const int maplength      = 256;                       // always
01398   const int numcolorsphase = 16;
01399   const int numcolorsmag   = 16;
01400   // (numcolorsphase*numcolorsmag==maplength)
01401 
01402   // ______ First create a cmap for phase with 16 colors (subsample) ______
01403   makecmap(CMAP,input);
01404   unsigned char CMAP_PHA16[3][16];
01405   int i,rgb;
01406   for (i=0; i<numcolorsphase; ++i)
01407     for (rgb=0; rgb<3; ++rgb)
01408       CMAP_PHA16[rgb][i] = CMAP[rgb][int(numcolorsphase/2)+i*numcolorsphase];
01409 
01410   if (input.verbose==true)
01411     {
01412     cerr << "\nColromap for phase (16):\n";
01413     for (int ii=0; ii<16; ++ii)
01414       cerr << int(CMAP_PHA16[0][ii]) << " "
01415            << int(CMAP_PHA16[1][ii]) << " "
01416            << int(CMAP_PHA16[2][ii]) << "\n";
01417     cerr << "\n";
01418     }
01419 
01420   for (i=0; i<256; ++i)
01421     {
01422     int magnitudelevel = int(i/numcolorsphase);         // e[0:15]
01423     float level        = float(magnitudelevel)/float(numcolorsmag-1);// e[0,1]
01424     // ______ And add the gray colormap for the magnitude ______
01425     for (rgb=0; rgb<3; ++rgb)
01426       CMAP[rgb][i] = uchar(level*CMAP_PHA16[rgb][i%numcolorsphase]);
01427     }
01428   // ______ Display colormap for testing ______
01429   if (input.verbose==true)
01430     {
01431     #define VERBOSE
01432     #ifdef VERBOSE
01433     cerr << "\nWriting color table for SUNraster (mixed mag/phase):\n";
01434     for (int ii=0; ii<maplength; ++ii)
01435       cerr << int(CMAP[0][ii]) << " "
01436            << int(CMAP[1][ii]) << " "
01437            << int(CMAP[2][ii]) << "\n";
01438     #endif
01439     }
01440   } // END makecmapmixed
01441 
01442 
01443 /****************************************************************
01444  * handleinput                                                  *
01445  * return input options/arguments                               *
01446  #%// BK 11-May-2000                                            *
01447  ****************************************************************/
01448 bool handleinput(
01449         int argc,
01450         char* argv[],
01451         commandlineinput &input)
01452   {
01453   // at least      "prog -h"
01454   // at least      "prog -w 123 file" or "prog -w123 file"
01455   // leaves argc = " 1    2  3   4  "    " 1     2     3 "
01456   // if (argc < 3) {cerr << "argc: " << argc << endl; return false;} // speed
01457   //if (argc==1) {cerr << "argc: " << argc << endl; return false;} // speed
01458   if (argc==1) return false; // speed
01459 
01460   bool allmandatory = true;
01461   extern char *optarg;
01462   //extern int optind,opterr,optopt;
01463   extern int optind;
01464   int c;
01465 
01466   // ______ Set defaults ______
01467   input.linelength  = 0;
01468   input.iformat     = FORMATCR4;        // default
01469   input.oformat     = ASCII;            // default readable output to screen 
01470   input.dooutput    = MAGNITUDE;        // default magnitude
01471   input.exponent    = 1.;               // default
01472   input.scale       = 1.;               // default
01473   input.firstline   = 1;                // default
01474   input.lastline    = -1;               // compute last line
01475   input.firstpixel  = 1;                // default
01476   input.lastpixel   = -1;               // compute last pixel
01477   input.sublines    = 1;
01478   input.subpixels   = 1;
01479   input.multilookL  = 1;
01480   input.multilookP  = 1;
01481   input.headerlength = 0;               // default
01482   input.mirrorX     = NOMIRROR;         // default
01483   input.mirrorY     = NOMIRROR;         // default
01484   strcpy(input.cmap,"default");         // default (mag. gray/ otherwise hsv)
01485   //strcpy(input.cmap,"gray");          // default (mag.)
01486   input.numlines    = 0;
01487   input.dontohx     = false;            // default
01488   input.dohtonx     = false;            // default
01489   input.verbose     = false;            // default
01490   input.scalebar    = false;            // default
01491   input.realinput   = false;            // default cpx files
01492 
01493   // ______ Get commandline ______
01494   char OPTSTRING[40] = "w:e:f:l:L:m:o:p:P:q:s:S:M:c:B:H:bhV";
01495   while ((c = getopt(argc, argv, OPTSTRING)) != -1)
01496     {
01497     switch (c)
01498       {
01499       case 'w':
01500         input.linelength  = atoi(optarg);
01501         break;
01502       case 'e':
01503         input.exponent    = atof(optarg);
01504         break;
01505       case 's':
01506         input.scale       = atof(optarg);
01507         break;
01508       case 'l':
01509         input.firstline   = atoi(optarg);
01510         break;
01511       case 'L':
01512         input.lastline    = atoi(optarg);
01513         break;
01514       case 'p':
01515         input.firstpixel  = atoi(optarg);
01516         break;
01517       case 'P':
01518         input.lastpixel   = atoi(optarg);
01519         break;
01520       case 'S':         // subsample -Mp/l == -Mx/y == -M1/5
01521         {
01522         int i=0;
01523         char subP[8];
01524         while (optarg[i] != '/' && optarg[i] != '\0')
01525           {
01526           subP[i] = optarg[i];
01527           ++i;
01528           }
01529         subP[i]='\0';
01530         char subL[8];
01531         int j=0;
01532         for (j=0; j<sizeof(optarg)-i; ++j)
01533           subL[j] = optarg[j+i+1];
01534         subL[j]='\0';
01535         input.sublines  = atoi(subL);
01536         input.subpixels = atoi(subP);
01537         if (input.sublines  < 1) input.sublines = 1;
01538         if (input.subpixels < 1) input.subpixels = 1;
01539         break;
01540         }
01541       case 'q':
01542         if (!strcmp(optarg,"mag"))
01543           input.dooutput = MAGNITUDE;
01544         else if (!strcmp(optarg,"phase"))
01545           input.dooutput = PHASE;
01546         else if (!strcmp(optarg,"real"))
01547           input.dooutput = REALPART;
01548         else if (!strcmp(optarg,"imag"))
01549           input.dooutput = IMAGPART;
01550         else if (!strcmp(optarg,"normal"))
01551           input.dooutput = NORMAL;
01552         else if (!strcmp(optarg,"mixed"))
01553           input.dooutput = MIXED;
01554         else
01555           {
01556           cerr << argv[0] << ": ERROR: -q mag|phase|real|imag|normal|mixed: ~= "
01557                << optarg << endl;
01558           synopsis(argv[0]);
01559           }
01560         break;
01561       case 'f':
01562         if (!strcmp(optarg,"cc1"))
01563           input.iformat = FORMATCC1;
01564         else if (!strcmp(optarg,"cuc1"))
01565           input.iformat = FORMATCUC1;
01566         else if (!strcmp(optarg,"ci2"))
01567           input.iformat = FORMATCI2;
01568         else if (!strcmp(optarg,"ci4"))
01569           input.iformat = FORMATCI4;
01570         else if (!strcmp(optarg,"cr4"))
01571           input.iformat = FORMATCR4;
01572         else if (!strcmp(optarg,"cr8"))
01573           input.iformat = FORMATCR8;
01574         // add char input, though it is not complex...
01575         else if (!strcmp(optarg,"c1"))
01576           input.iformat = FORMATUC1;
01577         // add i2 input, though it is not complex...
01578         else if (!strcmp(optarg,"i2"))
01579           input.iformat = FORMATI2;
01580         // add real4 input, though it is not complex...
01581         else if (!strcmp(optarg,"r4"))
01582           input.iformat = FORMATR4;
01583         // add real8 input, though it is not complex...
01584         else if (!strcmp(optarg,"r8"))
01585           input.iformat = FORMATR8;
01586         else
01587           {
01588           cerr << argv[0] << ": ERROR: -f cc1|cuc1|ci2|ci4|cr4|cr8: ~= "
01589                << optarg << endl;
01590           synopsis(argv[0]);
01591           }
01592         break;
01593       case 'o':
01594         if (!strcmp(optarg,"ascii"))
01595           input.oformat = ASCII;
01596         else if (!strcmp(optarg,"float"))
01597           input.oformat = FORMATR4;
01598         else if (!strcmp(optarg,"short"))
01599           input.oformat = FORMATI2;
01600         else if (!strcmp(optarg,"uchar"))
01601           input.oformat = FORMATUC1;
01602         else if (!strcmp(optarg,"sunraster"))
01603           input.oformat = SUNRASTER;
01604         else
01605           {
01606           cerr << argv[0] << ": ERROR: -o ascii|float|short|uchar|sunraster ~= "
01607           << optarg << endl;
01608           synopsis(argv[0]);
01609           }
01610         break;
01611       case 'm':
01612         if (!strcmp(optarg,"XY") || !strcmp(optarg,"YX"))
01613           {
01614           input.mirrorX = DOMIRROR;
01615           input.mirrorY = DOMIRROR;
01616           }
01617         else if (!strcmp(optarg,"X"))
01618           input.mirrorX = DOMIRROR;
01619         else if (!strcmp(optarg,"Y"))
01620           input.mirrorY = DOMIRROR;
01621         else
01622           {
01623           cerr << argv[0] << ": ERROR: -m XY|YX|X|Y: " << optarg << endl;
01624           synopsis(argv[0]);
01625           }
01626         break;
01627       case 'M':         // multilook -Mp/l == -Mx/y == -M1/5
01628         {
01629         int i=0;
01630         char mlP[8];
01631         while (optarg[i] != '/' && optarg[i] != '\0')
01632           {
01633           mlP[i] = optarg[i];
01634           ++i;
01635           }
01636         mlP[i]='\0';
01637         int j=0;
01638         char mlL[8];
01639         for (j=0; j<sizeof(optarg)-i; ++j)
01640           mlL[j] = optarg[j+i+1];
01641         mlL[j]='\0';
01642         input.multilookL = atoi(mlL);
01643         input.multilookP = atoi(mlP);
01644         if (input.multilookL < 1) input.multilookL = 1;
01645         if (input.multilookP < 1) input.multilookP = 1;
01646         break;
01647         }
01648       case 'c':
01649         strcpy(input.cmap,optarg);
01650         break;
01651       case 'B':
01652         if (!strcmp(optarg,"s"))
01653           input.dontohx = true;
01654         else if (!strcmp(optarg,"b"))
01655           input.dohtonx = true;
01656         else
01657           cerr << argv[0] << ": option to -B not recognized, continuing w/o swapping.\n";
01658         break;
01659       case 'H':
01660         input.headerlength = atoi(optarg);
01661         break;
01662       case 'b':
01663         input.scalebar = true;
01664         break;
01665       case 'V':
01666         input.verbose = true;
01667         break;
01668       case 'h':
01669         usage(argv[0]);
01670         break;
01671       case '?':
01672         synopsis(argv[0]);
01673       } // switch
01674     } // commandlineoptions
01675 
01676   // ______ Check input ______
01677   if (input.linelength == 0)
01678     {
01679     cerr << argv[0] << ": ERROR: No width specified.\n";
01680     return false;
01681     }
01682 
01683   // filename: last argument
01684   // cerr << "OPTARG: " << argv[argc-1] << endl;
01685   // cerr << "OPTARG: " << argv[optind] << endl;
01686   if (argv[optind]=='\0')
01687     {
01688     cerr << argv[0] << ": ERROR: No input file specified.\n";
01689     return false;
01690     }
01691   strcpy(input.ifile,argv[optind]);
01692 
01693   // ______ Check for: "cpxfiddle --help" ______
01694   if (!strcmp(input.ifile,"help"))
01695     usage(argv[0]);
01696 
01697   // ____ new option for real4 input, not intented usage _____
01698   // ____ outformat must be normal for this _____
01699   // BK 13-Apr-2003
01700   if (input.iformat == FORMATR8  || 
01701       input.iformat == FORMATR4  || 
01702       input.iformat == FORMATUC1 || 
01703       input.iformat == FORMATI2)
01704     input.realinput = true;
01705   if (input.realinput)
01706     {
01707     if (input.dooutput != NORMAL)
01708       {
01709       cerr << argv[0] << ": ERROR: for real input formats, use -q normal\n";
01710       usage(argv[0]);
01711       }
01712     }
01713 
01714   // ______ Compute numlines ______
01715   // rather either numlines or width and compute the other.
01716   //ifstream infile(input.ifile, ios::in | ios::nocreate);
01717   ifstream infile(input.ifile, ios::in);
01718   if (!infile)
01719     {
01720     cerr << argv[0] << ": ERROR: inputfile: " << input.ifile << "not found.\n";
01721     synopsis(argv[0]);
01722     }
01723   infile.seekg(0,ios::end);                    // filepointer at end
01724   const int fsize = int(infile.tellg()) - input.headerlength;// account for e.g., 32 byte header
01725   infile.close();
01726   input.bytesperelement = input.iformat%10;     // real/imag is read seperately
01727   input.bytesperpixel   = 2*input.bytesperelement;// per complex pixel
01728   // ____ adapt bytes per pixel for real input.  -q normal must be ____
01729   // BK 13-Apr-2003
01730   if (input.realinput)
01731     {
01732     cerr << argv[0] << ": WARNING: using real input, width in non-complex pixels\n";
01733     input.bytesperpixel   = input.bytesperelement;// hopefully this is we have to do
01734     }
01735   input.numlines        = fsize / input.bytesperpixel / input.linelength;
01736   input.bytesperline    = input.bytesperpixel * input.linelength;
01737 
01738   // ______ Set other defaults ______
01739   if (input.lastline==-1)  input.lastline  = input.numlines;
01740   if (input.lastpixel==-1) input.lastpixel = input.linelength;
01741 
01742   // ______ Check wrong... ______
01743   if (input.lastline>input.numlines)
01744     {
01745     cerr << "#" << argv[0]
01746       << ": WARNING: -L: lastline>numlines; continuing with numlines of file.\n"; 
01747     input.lastline = input.numlines;
01748     }
01749   if (input.lastpixel>input.linelength)
01750     {
01751     cerr << "#" << argv[0] 
01752       << ": WARNING: -P: lastpixel>numpixels; continuing with width of file.\n";
01753     input.lastpixel = input.linelength;
01754     }
01755   if (input.numlines*input.linelength*input.bytesperpixel != fsize)
01756     {
01757     cerr << argv[0] << ": ERROR: -w does not seem ok (checked with numlines*bytes)\n";
01758     cerr << argv[0] << ": ERROR: but continuing, see it yourself...\n\a\a";
01759     //synopsis(argv[0]);
01760     }
01761   if (input.lastline<input.firstline)
01762     {
01763     cerr << argv[0] << ": ERROR: -l -L: lastline<firstline\n";
01764     synopsis(argv[0]);
01765     }
01766   if (input.lastpixel<input.firstpixel)
01767     {
01768     cerr << argv[0] << ": ERROR: -p -P: lastpixel<firstpixel\n";
01769     synopsis(argv[0]);
01770     }
01771 
01772   // ______ Set default cmap if not specified ______
01773   if (input.oformat==SUNRASTER)
01774     if (!strcmp(input.cmap,"default"))
01775       (input.dooutput==MAGNITUDE) ? 
01776         strcpy(input.cmap,"gray") : strcpy(input.cmap,"hsv");
01777 
01778   if (input.dooutput==PHASE)
01779     {
01780     if (input.exponent != 1.) cerr << "#WARNING: -e: exponent for phase output?\n";
01781     if (input.scale    != 1.) cerr << "#WARNING: -s: scale for phase output?\n";
01782     if (input.scale   == -1.) cerr << "#-s -1: ok, flipping phase.\n";
01783     if (input.oformat==SUNRASTER)
01784       if (!strcmp(input.cmap,"gray"))
01785         cerr << "Tip -c changes colormap, e.g. -c hot\n";
01786     }
01787   if (input.dooutput==MIXED)
01788     {
01789     if (input.oformat!=SUNRASTER && input.oformat!=FORMATUC1)
01790       {
01791       cerr << "ERROR: -q MIXED only for -o sunraster/uc1\n";
01792       synopsis(argv[0]);
01793       }
01794     else
01795       {
01796       if (!strcmp(input.cmap,"gray"))
01797         {
01798         cerr << "#WARNING: -q mixed: changing phase colormap from gray to hot (-c)\n";
01799         strcpy(input.cmap,"hot");
01800         }
01801       }
01802     }
01803   if (input.scalebar==true && input.oformat!=SUNRASTER)
01804     {
01805     cerr << "ERROR: -b only for sunraster phase/mixed\n";
01806     synopsis(argv[0]);
01807     }
01808   if (input.multilookL!=1 && input.sublines!=1)
01809     {
01810     cerr << argv[0] << ": ERROR: -M -Y: no subsampling and multilooking allowed.\n";
01811     synopsis(argv[0]);
01812     }
01813   if (input.multilookP!=1 && input.subpixels!=1)
01814     {
01815     cerr << argv[0] 
01816          << ": ERROR: -M -X: no subsampling and multilooking allowed.\n";
01817     synopsis(argv[0]);
01818     }
01819 
01820 
01821   // ______ give tip ______
01822   if (input.oformat==FORMATUC1 && input.dooutput==PHASE)
01823     cerr << argv[0] 
01824     << ": TIP: display with (ImageMagick, FILE is redirected file):\ndisplay -size "
01825     << input.linelength << "x" << input.numlines << " gray:FILE\n";
01826     
01827 
01828   // ____ be verbose if required ______
01829   if (input.verbose==true)
01830     {
01831     cerr                   << argv[0]               << " variables:\n" <<
01832     " linelength:        " << input.linelength      << "\n" <<
01833     " ifile:             " << input.ifile           << "\n" <<
01834     " iformat:           " << input.iformat         << "\n" <<
01835     " exponent:          " << input.exponent        << "\n" <<
01836     " scale:             " << input.scale           << "\n" <<
01837     " firstline:         " << input.firstline       << "\n" <<
01838     " lastline:          " << input.lastline        << "\n" <<
01839     " firstpixel:        " << input.firstpixel      << "\n" <<
01840     " lastpixel:         " << input.lastpixel       << "\n" <<
01841     " sublines:          " << input.sublines        << "\n" <<
01842     " subpixels:         " << input.subpixels       << "\n" <<
01843     " dooutput:          " << input.dooutput        << "\n" <<
01844     " oformat:           " << input.oformat         << "\n" <<
01845     " dohtonx:           " << input.dohtonx         << "\n" <<
01846     " dontohx:           " << input.dontohx         << "\n" <<
01847     " scalebar:          " << input.scalebar        << "\n" <<
01848     " mirrorX:           " << input.mirrorX         << "\n" <<
01849     " mirrorY:           " << input.mirrorY         << "\n" <<
01850     " multilookX:        " << input.multilookP      << "\n" <<
01851     " multilookY:        " << input.multilookL      << "\n" <<
01852     " cmap:              " << input.cmap            << "\n" <<
01853     " skip header bytes: " << input.headerlength    << "\n" <<
01854     " numlines:          " << input.numlines        << "\n" <<
01855     " bytesperelement:   " << input.bytesperelement << "\n" <<
01856     " bytesperpixel:     " << input.bytesperpixel   << "\n" <<
01857     " bytesperline:      " << input.bytesperline    << "\n";
01858     }
01859 
01860   // ______ Set variables used in 'functie' to multilook ______
01861   if (input.multilookL != 1)
01862     input.sublines = input.multilookL;                  // use this to set filepointer
01863   if (input.multilookP != 1)
01864     input.subpixels = input.multilookP;                 // use this to set filepointer
01865 
01866   return allmandatory;
01867   } // END handleinput
01868 
01869 
01870 /****************************************************************
01871  * shortexpl                                                    *
01872  * for synopsis and usage                                       *
01873  #%// BK 11-May-2000                                            *
01874  ****************************************************************/
01875 void shortexpl()
01876   {
01877   cerr << "\n   Dump content of complex binary file to stdout,"
01878        << "\n    either: as is, magnitude, phase, real or imaginary part."
01879        << "\n   Input files can be almost any complex file"
01880        << "\n    though not (yet) band interleaved."
01881        << "\n   Output can be manipulated by:"
01882        << "\n   multilooking, subsampling, mirroring, scaling, etc."
01883        << "\n   This program is useful for cropping and displaying, in combination"
01884        << "\n   with e.g., GMT, ImageMagick, or xv."
01885        << "\n   Output format to stdout can be binary."
01886        << "\n   Careful! only pipe or redirect this."
01887        << "\n   (use: \"cpxfiddle -h |& more\" for more help.)"
01888        << endl;
01889   } // END shortexpl
01890 
01891 /****************************************************************
01892  * synopsis                                                     *
01893  #%// BK 11-May-2000                                            *
01894  ****************************************************************/
01895 void synopsis(char *programname)
01896   {
01897   cerr << "\n  PROGRAM: " << programname 
01898        << " (version " << SWVERSION << ")\n";
01899   cerr << "\n  SYNOPSIS:\n\t" << programname
01900        << " -w width [-f informat] [-q output] [-o outformat]"
01901        << "\n\t[-e exp] [-s scale] [-l line]"
01902        << " [-L line] [-p pixel] [-P pixel]"
01903        << "\n\t[-S x/y] [-M x/y] [-m mirror] [-c file]"
01904        << " [-B swap] [-H bytes]"
01905        << "\n\t[-V] [-b] [-h[elp]] "
01906        << "[--] inputfile\n";
01907   shortexpl();
01908   cerr << endl;
01909   exit(-1);
01910   } // END synopsis
01911 
01912 
01913 
01914 /****************************************************************
01915  * usage                                                        *
01916  #%// BK 11-May-2000                                            *
01917  ****************************************************************/
01918 void usage(char *programname)
01919   {
01920   cerr << "\n  PROGRAM: " << programname
01921        << " (version " << SWVERSION << ")\n";
01922 
01923   shortexpl();
01924   cerr << "\n\n"
01925        << "\n\t   1   range (X) -->"
01926        << "\n\t 1  ---------------------"
01927        << "\n\t   |                     | "
01928        << "\n\t   |  <Complex file>     |"
01929        << "\n\t   | e.g. float (2x4B)   |  azimuth (Y)"
01930        << "\n\t   |  format             |    |"
01931        << "\n\t   |                     |    |"
01932        << "\n\t   | (major row order)   |    |"
01933        << "\n\t   | (pixel interleav.)  |    \\/"
01934        << "\n\t   |                     | "
01935        << "\n\t    ---------------------\n"
01936 
01937        << "\n   First a cutout is made,"
01938        << "\n   then the data is mirrored,"
01939        << "\n   and afterwards multilooked or subsampled,"
01940        << "\n   and finally the data is scaled and exp-ed."
01941        << "\n   This explains why a mirrored image is not equal to"
01942        << "\n   the original if the number of lines cannot be exactly"
01943        << "\n   divided by the multilook or subsampling factor.\n"
01944 
01945        << "\n\n  DESCRIPTION [default]:"
01946        << "\n   -w mandatory      Line length (width, rangepixels, X direction)"
01947        << "\n   -e [1.0]          Exponent: out=scale*output^exp"
01948        << "\n   -s [1.0]          Scale     out=scale*output^exp"
01949        << "\n   -l [1]            First (azimuth Y) line"
01950        << "\n   -L [all]          Last (azimuth Y) line"
01951        << "\n   -p [1]            First (range X) pixel"
01952        << "\n   -P [all]          Last (range X) pixel"
01953        << "\n   -M [1/1]          Multilook factor in X/Y direction (range/azimuth)"
01954        << "\n                      No subsampling can be used combined with this"
01955        << "\n                      option. (Multilooking takes complex sum over"
01956        << "\n                       window(X,Y), divides by number of looks)"
01957        << "\n                      Output size: [floor(P-p+1)/mlX; floor(L-l+1)/mlY]."
01958        << "\n   -S [1/1]          Subsample factor in X/Y (range/azimuth)"
01959        << "\n                      Output dimensionY = ceil((L-l+1)/Y)."
01960        << "\n                      The last line does not have to equal -L."
01961        << "\n                      Output dimensionX = ceil((P-p+1)/X)."
01962        << "\n                      The last pixel does not have to equal -P."
01963        << "\n   -q [mag]          What to output:"
01964        << "\n                     NORMAL | MAG | PHASE | MIXED | REAL | IMAG"
01965        << "\n                      normal    = (real, imag),"
01966        << "\n                      magnitude = sqrt(real^2 + imag^2),"
01967        << "\n                      phase     = atan2(imag,real),"
01968        << "\n                      mixed     = phase overlay, only with -o sunraster"
01969        << "\n                      real      = line[2*j],"
01970        << "\n                      imag      = line[2*j+1]."
01971        << "\n                     Normal option can be (mis)used to fiddle with, e.g.,"
01972        << "\n                      float files (though even linelength required?)."
01973        << "\n   -f [cr4]          Input format identifier:"
01974        << "\n                     CC1 | CUC1 | CI2 | CI4 | CR4 | CR8"
01975        << "\n                      for complex 2x1B char, unsigned char, "
01976        << "\n                      short integer, integer, float, double"
01977        << "\n                      (major row order pixel interleaved complex data.)"
01978        << "\n   -o [ascii]        Output format identifier (to stdout):"
01979        << "\n                     UCHAR | SUNRASTER | FLOAT | SHORT | ASCII"
01980        << "\n                      uchar, short, sunraster, and float options"
01981        << "\n                      write binary to stdout!"
01982        << "\n   -c [gray]         Colormap for \"-o sunraster\" option."
01983        << "\n                      FILENAME | GRAY | JET | HOT | COOL | BERT | HSV"
01984        << "\n                     If cmap is a filename, then a ascii file with"
01985        << "\n                     256 lines, containing r g b [0:255] is assumed."
01986        << "\n                     If cmap is a identifier, this colormap is used."
01987        << "\n   -m code           Flag to mirror file content in X or Y direction:"
01988        << "\n                     X | Y | XY | YX"
01989        << "\n                      If mirroring Y then the first output line is"
01990        << "\n                      line number P (default last in file). This means"
01991        << "\n                      that if -Y is specified, the last line not"
01992        << "\n                      necessarely is line -l (firstline default 1)"
01993        << "\n                      The same is true for mirroring in X direction."
01994        << "\n   -B b|s            Swap bytes."
01995        << "\n                      if -Bs then swap to host order."
01996        << "\n                       (call ntohs or ntohl, thus swapping from big endian"
01997        << "\n                       to host type, which is small endian for X86 PC's.)"
01998        << "\n                      if -Bb then swap to network order."
01999        << "\n                       (call htons or htonl, thus swapping to big endian"
02000        << "\n                       from host type, which is small endian for X86 PC's.)"
02001        << "\n                      On a big endian platform both these functions are"
02002        << "\n                      defined as NULL macros, and do nothing."
02003        << "\n   -b                Add a scalebar in lower right corner for -o sunraster"
02004        << "\n                      Only for -q phase and mixed."
02005        << "\n   -H bytes          Skip Header bytes, e.g., for GENESIS SUNraster floats."
02006        << "\n   -V                Verbose."
02007        << "\n   -h[elp]           This help."
02008 
02009        << endl
02010        << "\n\n  EXAMPLES:"
02011        << "\n   Check first few values in complex short file (width 100, height 200):"
02012        << "\n      " << programname << " -w100 -fci2 -qnormal -oascii -L5 -P3 -V -- cpxfile"
02013        << endl
02014        << "\n   To generate a grd file for use with GMT, without creating a large"
02015        << "\n   tmpfile, use something like:"
02016        << "\n      " << programname << " -w100 -fci2 -qphase -ofloat -- cpxfile | \\"
02017        << "\n      " << " xyz2grd -Gfile.grd -R1/100/1/200 -Zf"
02018        << endl
02019        << "\n   To crop a binary complex float file of width 781 and height 501:"
02020        << "\n   (redirect, or your screen will be flooded with binary output!)"
02021        << "\n      " << programname << " -w781 -fcr4 -qnormal -ofloat -l101 -L200 \\"
02022        << "\n      " << " -p51 -P750 cpxfile > cpxfile.cropped"
02023        << endl
02024        << "\n   To convert the phase of the same file to SUNraster format:"
02025        << "\n      " << programname << " -w781 -fcr4 -qphase -osunraster \\"
02026        << "\n      " << " -ccmap.rainbow -- cpxfile > phase.ras"
02027        << "\n      display phase.ras"
02028        << "\n   Where the colortable file is generated by (using GMT):"
02029        << "\n      makecpt -Crainbow -T0/256/1 | \\"
02030        << "\n        awk '{if (NR>3&&NR<260){print $2, $3, $4}}' > cmap.rainbow"
02031        << endl
02032        << "\n   To create a sort of 8 bit pixmap, visualize with ImageMagick's"
02033        << "\n   display as gray format:"
02034        << "\n      " << programname << " -qphase -fcr4 -ouchar -w1 -- cpxfile > phase.uc"
02035        << "\n      display -size 781x501 gray:phase.uc"
02036        << "\n   The file phase.uc could also be converted to another format, e.g.:"
02037        << "\n      rawtopgm 781 501 phase.uc > phase.pgm"
02038        << "\n      xv phase.pgm"
02039        << endl
02040        << "\n   But easier would have been to use " << programname 
02041        << " to generate the"
02042        << "\n   SUNraster file. This can be done by:"
02043        << "\n      " << programname << " -w100 -qmag -osunraster -e0.3 -s1.1 file.cr4 > file.ras"
02044        << endl
02045        << "\n   Where file.cr4 is complex real4, -e is used to equalize the "
02046        << "\n   histogram, and -s to threshold the data (larger scale means"
02047        << "\n   more white). To overlay the phase as layer over the magnitude:"
02048        << "\n      " << programname << " -w100 -qmixed -osunraster -e0.3 -- file.cr4 > file.ras"
02049        << "\n      " << "xv file.ras"
02050        << endl
02051        << "\n\n   To read the header of a (non complex!) sunraster file "
02052        << "\n      (8 int32 values):"
02053        << "\n      " << programname << " -w1 -L4 -qnormal -fci4 -- file.ras"
02054        << "\n   This program can be tricked to crop float files (non complex)"
02055        << "\n   This program can be used for conversions of files, trick with -w1"
02056        << "\n   To crop a bigendian file on a linux PC, swap and crop like:"
02057        << "\n      " << programname << " -w100 -fci2 -qnormal -oshort -Bs -- cpxfile > newfile"
02058 
02059        << endl
02060        << "\n\n   To read the content of a (non complex!) float vector with 32 byte header"
02061        << "\n      " << programname << " -w1 -qnormal -fr4 -H32  -oascii -- file.ras"
02062 
02063        << endl
02064        << "\n\n  BUGS:"
02065        << "\n   -M with -m:   First mirrored then multilooked."
02066        << "\n   -B:           Not tested properly, but simply calls functions."
02067        << "\n   all:          If cpxfile is a symbolic link, filesize cannot be"
02068        << "\n                 determined, and therefor the number of lines."
02069        << "\n                 Solution: Use the full path or use a hard link."
02070        << "\n   (lot of options, binary to screen, but these are features.)"
02071 
02072        << endl
02073        << "\n\n  SEE ALSO:"
02074        << "\n   cpx2ps, display, rawtopgm, makecpt (GMT)"
02075 
02076        << "\n\n  Please send your comments to:"
02077        << "\n   Bert Kampes, kampes@geo.tudelft.nl"
02078        << "\n   (BTW: view this help by piping stderr: " << programname << " -h |& more"
02079        << endl << endl;
02080   exit(-1);
02081   } // END usage
02082 
02083 
02084 

Generated on Fri Apr 22 15:57:51 2005 for Doris by doxygen 1.3.6