home *** CD-ROM | disk | FTP | other *** search
/ GRIPS 2: Government Rast…rocessing Software & Data / GRIPS_2.cdr / dos / imdisp / source / imagutil.c < prev    next >
C/C++ Source or Header  |  1990-11-20  |  20KB  |  574 lines

  1. /*************************************************************/
  2. /*  Copyright (C) 1989, California Institute of Technology   */
  3. /*  U. S. Government Sponsorship under NASA Contract         */
  4. /*  NAS7-918 is acknowledged.                                */
  5. /*************************************************************/
  6.  
  7. /***  IMDISP module IMAGUTIL.C
  8.  
  9.       Special Purpose Device Independant Display Routines
  10.  
  11.     Contains high level display routines such as interactive palette
  12.     adjustment, histogram display, and image profile drawing.
  13. ***/
  14.  
  15. /* Changed 10/6/87 to read cursor keys without numlock - mdm */
  16.  
  17. /* * * * INCLUDE files * * * */
  18.  
  19. #include  <conio.h>
  20. #include  <math.h>
  21. #include  <stdio.h>
  22. #include  <stdlib.h>
  23. #include  <string.h>
  24. #include  "imdef.h"
  25. #include  "imdisp.h"
  26. #include  "dispio.h"
  27. #include  "disputil.h"
  28.  
  29. /* * * * External functions * * * */
  30.  
  31. /* * * * Function declarations * * * */
  32.  
  33. int  DiddlePalette (int );
  34. int  DisplayHistogram (long *,int ,int ,int );
  35. int  Stretch (int ,int );
  36. int  Profile (void);
  37. void DoNegative(void);
  38. void ShowPalette( int);
  39. void ErasePalette( int);
  40.  
  41. /* * * * Global Variables * * * */
  42.  
  43.  
  44.  
  45. int DiddlePalette( int numdiddle)
  46.  
  47. /***  DiddlePalette performs interactive adjustment of the color
  48.     palette.  A wedge of numdiddle DN values, from 0 to the maximum,
  49.     is displayed at the bottom of the screen, and the palette is
  50.     changed to have only numdiddle distinct shades.  Then a loop
  51.     for user input is entered.  The active color is the one in the
  52.     wedge with the small black box inside it.
  53.  
  54.     The following is a list of commands:
  55.        Character      Action
  56.          7 (HOME)   move to first color in wedge
  57.          4 (6)      move to next lower (higher) color in wedge
  58.         ^4 (^6)     move 8 steps lower (higher) in wedge
  59.          r (R)      decrease (increase) amount of red one notch
  60.          g (G)      decrease (increase) amount of green one notch
  61.          b (B)      decrease (increase) amount of blue one notch
  62.          S          scroll palette right
  63.          s          scroll palette left
  64.          2 (8)      decrease (increase) amount of all colors one notch
  65.          1 (END)    move to last color in wedge
  66.          x (X)      invert color wedge
  67.          .          exit from palette diddle mode
  68.  
  69.     The wedge is erased after the user exits.
  70.  
  71.     Parameter   Type   Description
  72.      numdiddle   int   number of colors in the wedge and resulting palette
  73.  
  74. ***/
  75.  
  76. {
  77.     int  line, samp, i, box, DN, numbox, DNperbox, shade, numcol;
  78.     int  boxnl, boxns,  linepos, samppos, marksize, len;
  79.     int  colornum;
  80.     unsigned char  ch;                      /* mdm 10/6/87 */
  81.     unsigned char   PaletteLine[MAXDISPNS];
  82.     unsigned char   hold, holdr, holdg, holdb;
  83.     struct Color  coltab[256];
  84.     char dispstr[60];
  85.  
  86. /*  Set up some constants */
  87.     numbox = min (numDN, numdiddle);
  88.     DNperbox = numDN / numbox;
  89.     boxns = dispns / numbox;
  90.     boxnl = dispnl / 10;
  91.     marksize = 8;
  92.     linepos = dispnl - (boxnl / 2) - (marksize / 2);
  93.  
  94. /* Draw the palette on the bottom of the screen */
  95.     ShowPalette( numdiddle );
  96.  
  97. /* Reduce the number of colors in the palette to numbox */
  98.     ReadPalette (coltab);
  99.     for (box = 0;  box < numbox; box++)
  100.     {
  101.         DN = box*DNperbox;
  102.         for (i = DN;  i < DN+DNperbox;  i++)
  103.         {   coltab[i].r = coltab[DN].r;
  104.             coltab[i].g = coltab[DN].g;
  105.             coltab[i].b = coltab[DN].b;
  106.         }
  107.     }
  108.     WritePalette (coltab);
  109.  
  110.     box = numbox / 2;
  111.     samppos =  box*boxns - (boxns / 2) - (marksize / 2);
  112.     DrawBox (linepos, samppos, marksize, marksize, 0);
  113.     shade = /*max(*/ 256 / numshades /*, 16)*/;
  114.  
  115. /* Interactively adjust the palette */
  116.     do  {
  117.            /* Save EGA settings in colornun: (red) (grn) (blue) */
  118.         if (DisplayDevice == EGA350 || DisplayDevice == EGA480
  119.          || DisplayDevice == VGA480)
  120.         {
  121.             colornum = (int)(coltab[DN].r/64);
  122.             colornum = (colornum << 2) | (0x03 & (int)(coltab[DN].g/64));
  123.             colornum = (colornum << 2) | (0x03 & (int)(coltab[DN].b/64));
  124.            }
  125.  
  126.         if ((ch = getch()) == 0)    /* mdm 10/9/87 */
  127.           ch = 0x80 | getch();
  128.  
  129.         DN = (box-1)*DNperbox;
  130.         DrawBox (linepos, samppos, marksize, marksize, DN);
  131.  
  132.         switch (ch)
  133.         {
  134.         case 'r' :
  135.                  coltab[DN].r = coltab[DN].r - shade;
  136.                  if (coltab[DN].r < 0) coltab[DN].r = 255;
  137.                  break;
  138.         case 'R' :
  139.                  coltab[DN].r = (coltab[DN].r + shade)%256;
  140.                  /*min (coltab[DN].r + shade,255);*/
  141.                  break;
  142.         case 'g' :
  143.                  coltab[DN].g = coltab[DN].g - shade;
  144.                  if (coltab[DN].g < 0) coltab[DN].g = 255;
  145.                  break;
  146.         case 'G' :
  147.                  coltab[DN].g = (coltab[DN].g + shade)%256;
  148.                  /*min (coltab[DN].g + shade,255);*/
  149.                  break;
  150.         case 'b' :
  151.                  coltab[DN].b = max (coltab[DN].b - shade,0);
  152.                  if (coltab[DN].b < 0) coltab[DN].b = 255;
  153.                  break;
  154.         case 'B' :
  155.                  coltab[DN].b = (coltab[DN].b + shade)%256;
  156.                  /*min (coltab[DN].b + shade,255);*/
  157.                  break;
  158.         case 'X' :        /* xchange color table values */
  159.         case 'x' :
  160.                  for (i = 1; i <= numbox/2;  i++)
  161.                  {    hold               = coltab[numbox-i].r;
  162.                       coltab[numbox-i].r = coltab[i-1].r;
  163.                       coltab[i-1].r      = hold;
  164.                  
  165.                       hold               = coltab[numbox-i].g;
  166.                       coltab[numbox-i].g = coltab[i-1].g;
  167.                       coltab[i-1].g      = hold;
  168.                  
  169.                       hold               = coltab[numbox-i].b;
  170.                       coltab[numbox-i].b = coltab[i-1].b;
  171.                       coltab[i-1].b      = hold;
  172.                  }
  173.                  break;
  174.         case 'S' :        /* shift color table one right */
  175.                  holdr       = coltab[numbox-1].r;
  176.                  holdg       = coltab[numbox-1].g;
  177.                  holdb       = coltab[numbox-1].b;
  178.                  for (i = numbox-1; i > 0;  i--)
  179.                  {
  180.                       coltab[i].r = coltab[i-1].r;
  181.                       coltab[i].g = coltab[i-1].g;
  182.                       coltab[i].b = coltab[i-1].b;
  183.                  }
  184.                  coltab[0].r = holdr;
  185.                  coltab[0].g = holdg;
  186.                  coltab[0].b = holdb;
  187.                  break;
  188.         case 's' :        /* shift color table one left */
  189.                  holdr       = coltab[0].r;
  190.                  holdg       = coltab[0].g;
  191.                  holdb       = coltab[0].b;
  192.                  for (i = 1; i < numbox ;  i++)
  193.                  {
  194.                       coltab[i-1].r = coltab[i].r;
  195.                       coltab[i-1].g = coltab[i].g;
  196.                       coltab[i-1].b = coltab[i].b;
  197.                  }
  198.                  coltab[numbox-1].r = holdr;
  199.                  coltab[numbox-1].g = holdg;
  200.                  coltab[numbox-1].b = holdb;
  201.                  break;
  202.         case DOWN_ARROW:
  203.         case '2' :
  204.          if ( (DisplayDevice == EGA350 || DisplayDevice == EGA480)
  205.             && numshades == 4)
  206.          {
  207.                --colornum;
  208.                coltab[DN].b = 64 * (colornum & 0x03);
  209.                coltab[DN].g = 64 * ((colornum >> 2) & 0x03);
  210.                coltab[DN].r = 64 * ((colornum >> 4) & 0x03);
  211.          }
  212.          else
  213.          {
  214.                      coltab[DN].r = coltab[DN].r - shade;
  215.                      coltab[DN].g = coltab[DN].g - shade;
  216.                      coltab[DN].b = coltab[DN].b - shade;
  217.             }
  218.                  break;
  219.         case UP_ARROW:
  220.         case '8' :
  221.          if ( (DisplayDevice == EGA350 || DisplayDevice == EGA480)
  222.             && numshades == 4)
  223.          {
  224.                ++colornum;
  225.                coltab[DN].b = 64 * (colornum & 0x03);
  226.                coltab[DN].g = 64 * ((colornum >> 2) & 0x03);
  227.                coltab[DN].r = 64 * ((colornum >> 4) & 0x03);
  228.             } else {
  229.             /*
  230.                      coltab[DN].r = min (coltab[DN].r + shade,255);
  231.                      coltab[DN].g = min (coltab[DN].g + shade,255);
  232.                      coltab[DN].b = min (coltab[DN].b + shade,255);
  233.             */
  234.                         coltab[DN].r = (coltab[DN].r + shade) % 256;
  235.                      coltab[DN].g = (coltab[DN].g + shade) % 256;
  236.                      coltab[DN].b = (coltab[DN].b + shade) % 256;
  237.             }
  238.                  break;
  239.         case RIGHT_ARROW:
  240.         case '6' :
  241.                  box = min (box+1, numbox);
  242.                  goto Skip;
  243.         case LEFT_ARROW:
  244.         case '4' :
  245.                  box = max (box-1, 1);
  246.                  goto Skip;
  247.         case CONTROL_RIGHT_ARROW:
  248.                  box = min (box+(numDN>>3), numbox);
  249.                  goto Skip;
  250.         case CONTROL_LEFT_ARROW:
  251.                  box = max (box-(numDN>>3), 1);
  252.                  goto Skip;
  253.         case HOME:
  254.         case '7' :
  255.                  box = 1;
  256.                  goto Skip;
  257.         case END:
  258.         case '1' :
  259.                  box = numbox;
  260.                  goto Skip;
  261.         }
  262.         for (i = DN; i < DN+DNperbox;  i++)
  263.         {    coltab[i].r = coltab[DN].r;
  264.              coltab[i].g = coltab[DN].g;
  265.              coltab[i].b = coltab[DN].b;
  266.         }
  267.         WritePalette (coltab);
  268.  
  269.         Skip:
  270.         samppos =  box*boxns - (boxns / 2) - (marksize / 2);
  271.         DrawBox (linepos, samppos, marksize, marksize, 0);
  272.         DN = (box-1)*DNperbox;
  273.         sprintf( dispstr, "color = %2d red = %3d green = %3d blue = %3d",
  274.                 DN, coltab[DN].r, coltab[DN].g, coltab[DN].b);
  275.  
  276.         LengthText( dispstr, TextHeight, &len);
  277.         EraseText( TextLine, 1, TextHeight, len, 0);
  278.  
  279.         DrawText( dispstr, TextLine, 1, TextHeight, 0, numDN-1);
  280.  
  281.         if (ch == RETURN || ch == ESCAPE) ch = '.'; 
  282.     }
  283.     while (ch != '.');
  284.  
  285.  
  286. /* Erase the palette on the screen */
  287.     ErasePalette( numdiddle );
  288.  
  289. }
  290.  
  291.  
  292. int DisplayHistogram (long int * histbuf, int numbins, int minDN, int maxDN)
  293.  
  294. /***  DisplayHistogram diplays the passed histogram on the screen.
  295.     The third highest bin in the histogram is used to scale the
  296.     plot.  The axes of the plot are labeled and annotated.  The
  297.     number in each bin is indicated by the length of the line
  298.     drawn vertically from the axis.
  299.  
  300.      Parameter  Type            Description
  301.       histbuf   long int array  the array of count values for each bin
  302.       numbins   int             the number of bins in the histogram
  303.       minDN     int             the minimum DN value in the histogram
  304.       maxDN     int             the maximum DN value in the histogram
  305.  
  306. ***/
  307.  
  308. {
  309.     int     top, bottom, left, right, height, pixperbin, width;
  310.     int     i, DN, j, length, tic, tic_height=5;
  311.     int     num_Xtics=16, num_Ytics=10, num_Xlabels=8, num_Ylabels=5;
  312.     long    count, MaxCount;
  313.     char    dispstring[16];
  314.  
  315.  
  316.     top       = dispnl / 10;
  317.     bottom    = dispnl - top;
  318.     left      = dispns / 10;
  319.     right     = dispns - (dispns / 100);
  320.     height    = bottom - top;
  321.     pixperbin = (right - left) / numbins;
  322.     width     = (numbins+1)*pixperbin;
  323.     right     = left + width - 1;            /* reset right edge */
  324.  
  325.  
  326.     MaxCount = max3arr( histbuf, numbins);
  327.  
  328. /* Draw the x axis  (DN value) */
  329. /*    DrawLine (bottom, left, bottom, right, numDN-1); */
  330.     FrameBox( top, left, bottom, right, numDN-1, FALSE);
  331.     tic = (numbins / 16) * pixperbin;
  332.     tic_height = dispnl / 100;
  333. /* Put in the tic marks */
  334.     for (i = 0;  i <= num_Xtics;  i++)
  335.     {
  336.         j = left + pixperbin + i*tic;
  337.         DrawLine (bottom, j, bottom+tic_height, j, numDN-1);
  338.     }
  339. /* Put in the labels */
  340.     for (i = 0;  i <= num_Xlabels;  i++)
  341.     {
  342.         DN = i*0.125*((float)maxDN-minDN+1) + (float)minDN + 0.5;
  343.         if (DN < 0)  DN--;
  344.         sprintf (dispstring, "%3d", DN);
  345.         j = left + (((numbins*i) / 8) + 1)*pixperbin - 15;
  346.         DrawText (dispstring, bottom+20, j, SmallChars, 0, numDN-1);
  347.     }
  348. /* And write out the X-axis title */
  349.     DrawText ("DN value", bottom+40, left+(width / 2) - 75, TextHeight, 0, numDN-1);
  350.  
  351.  
  352. /* Draw the y axis  (Counts) */
  353. /*    DrawLine (bottom, left, top, left, numDN-1); */
  354.     for (i = 0;  i <= num_Ytics;  i++)
  355.     {
  356.         j = bottom - height*i/num_Ytics;
  357.         DrawLine (j, left, j, left-tic_height, numDN-1);
  358.     }
  359.     DrawText ("0", bottom-5, left-20, SmallChars, 0, numDN-1);
  360.     sprintf (dispstring, "%5ld", MaxCount);
  361.     DrawText (dispstring, bottom-height+5, left-60, SmallChars, 0, numDN-1);
  362.     DrawText ("Counts", bottom-(height / 2)+50, left-20, TextHeight, 90, numDN-1);
  363.  
  364.  
  365.  
  366. /* Draw the histogram lines */
  367.     j = left;
  368.     for (i = 0;  i < numbins;  i++)
  369.     {
  370.         j += pixperbin;
  371.         if (histbuf[i] > MaxCount)
  372.             length = height;
  373.         else
  374.             length = height*((float)histbuf[i]/(float)MaxCount) + 0.5;
  375.  
  376.         if (Color_Hist)
  377.           DrawLine (bottom, j, bottom-length, j, i); /* color histo */
  378.         else
  379.           DrawLine (bottom, j, bottom-length, j, numDN-1);
  380.     }
  381.  
  382. }
  383.  
  384. int Stretch (int DNlow, int DNhigh)
  385.  
  386. /***  Stretch applies a linear gray scale ramp to the palette
  387.     starting with 0 at Dnlow and proceeding to 255 at DNhigh.
  388.  
  389.      Parameter  Type   Description
  390.       DNlow     int    the starting DN value of the linear ramp
  391.       DNhigh    int    the ending DN value of the linear ramp
  392.  
  393. ***/
  394. /* int   DNlow, DNhigh; */
  395. {
  396.     struct  Color  CT[256];
  397.     float   slope;
  398.     int     i, shade;
  399.  
  400.  
  401.     if (DNhigh > numDN-1)   DNhigh = numDN-1;
  402.     if (DNhigh < 0)   DNhigh = numDN-1;
  403.     if (DNlow < 0)   DNlow = 0;
  404.     if (DNlow > numDN-1)   DNlow = 0;
  405.     slope = 256/ (float)(DNhigh - DNlow + 1);
  406.     for (i = 0;  i < numDN;  i++)
  407.     {
  408.         shade = slope*(i-DNlow) + 0.5;
  409.         if (shade < 0)   shade = 0;
  410.         if (shade > 255) shade = 255;
  411.         CT[i].r = shade;
  412.         CT[i].g = shade;
  413.         CT[i].b = shade;
  414.     }
  415.     WritePalette (CT);
  416. }
  417.  
  418. int Profile( void )
  419.  
  420. /***  Profile plots a profile of the pixel values between two points
  421.     on the screen.  Cursor mode is used to select the two endpoints.
  422.     A line is drawn between the endpoints and a plot of DN value
  423.     versus distance along the line is made.
  424. ***/
  425. {
  426.     int  line1, samp1, line2, samp2;
  427.     int  line, samp, distance, delline, delsamp;
  428.     int  bottom, left, height, width, top, right;
  429.     int  DN,  minDN, maxDN;
  430.     int  i, j, numpoints;
  431.     float  t, scalefact;
  432.     char   dispstring[64];
  433.     int    DNvalues[MAXDISPNL+MAXDISPNS];
  434.     int    Pixels[MAXDISPNL+MAXDISPNS];
  435.     unsigned char  SavePatch[CURSORSIZE][CURSORSIZE];
  436.  
  437.  
  438.     MoveCursor (&line1, &samp1);
  439.     PlaceCursor (line1, samp1, numDN-1);   CursorOn = 0;
  440.     for (i = 0;  i < CURSORSIZE; i++)
  441.         for (j = 0;  j < CURSORSIZE; j++)
  442.             SavePatch[i][j] = CursorPatch[i][j];
  443.     MoveCursor (&line2, &samp2);
  444.     for (i = 0;  i < CURSORSIZE; i++)
  445.         for (j = 0;  j < CURSORSIZE; j++)
  446.             CursorPatch[i][j] = SavePatch[i][j];
  447.     CursorOn = 1;   CursorLine = line1;  CursorSample = samp1;
  448.     RemoveCursor();
  449.     if (line1==line2 && samp1==samp2) return;
  450.     delline = line2 - line1;   delsamp = samp2 - samp1;
  451.     distance = sqrt(  (float)
  452.                ( (long)delline*delline + (long)delsamp*delsamp ) ) + 0.5;
  453.  
  454.  
  455.     bottom = dispnl - 45;      left = 60;
  456.     height = dispnl/3;         width = dispns - 150;
  457.     top = bottom - height;     right = left + width;
  458.  
  459.     minDN = 255;    maxDN = 0;
  460.     numpoints = distance;
  461.     if (numpoints > width / 2)   numpoints = width / 2;
  462.     for (i = 0;  i <= numpoints;  i++)
  463.     {
  464.         t = (float)i/numpoints;
  465.         line = line1 + (int)(delline*t+0.5);
  466.         samp = samp1 + (int)(delsamp*t+0.5);
  467.         ReadPixel (line, samp, &DN);
  468.         if (DN < minDN)   minDN = DN;
  469.         if (DN > maxDN)   maxDN = DN;
  470.         DNvalues[i] = DN;
  471.         Pixels[i] = (int)(width*t+0.5) + left;
  472.     }
  473.  
  474.     if (minDN == maxDN)   scalefact = 0;
  475.       else scalefact = (float)height/(maxDN - minDN);
  476.     for (i = 0;  i<= numpoints;  i++)
  477.         DNvalues[i] = bottom - (int)( scalefact*(DNvalues[i] - minDN) + 0.5);
  478.  
  479.  
  480.     DrawLine (line1, samp1,  line2, samp2, numDN-1);
  481.  
  482.           /* Draw the x axis  (Pixels) */
  483.     DrawLine (bottom, left, bottom, right, numDN-1);
  484.     DrawLine (bottom, right, bottom-5, right, numDN-1);
  485.     DrawText ("0", bottom+20, left, SmallChars, 0, numDN-1);
  486.     sprintf (dispstring, "%4d", distance);
  487.     DrawText (dispstring, bottom+20, right-30, SmallChars, 0, numDN-1);
  488.     DrawText ("Pixels", bottom+25, left+(width/2) - 70, TextHeight, 0, numDN-1);
  489.  
  490.  
  491.           /* Draw the y axis  (DN value) */
  492.     DrawLine (bottom, left, top, left, numDN-1);
  493.     DrawLine (top, left, top, left+5, numDN-1);
  494.     sprintf (dispstring, "%3d", minDN);
  495.     DrawText (dispstring, bottom-5, left-40, SmallChars, 0, numDN-1);
  496.     sprintf (dispstring, "%3d", maxDN);
  497.     DrawText (dispstring, top+5, left-40, SmallChars, 0, numDN-1);
  498.     DrawText ("DN Value", bottom-(height / 2)+50, left-30, TextHeight, 90, numDN-1);
  499.  
  500.  
  501.     for (i = 0;  i < numpoints; i++)
  502.         DrawLine (DNvalues[i], Pixels[i], DNvalues[i+1], Pixels[i+1], numDN-1);
  503.  
  504. }
  505.  
  506. void DoNegative(void)
  507. {
  508.     int i;
  509.     unsigned char hold;
  510.     struct Color  coltab[256];
  511.  
  512.     ReadPalette(coltab);
  513.  
  514.     for (i = 1; i <= numDN/2;  i++)
  515.     {    hold               = coltab[numDN-i].r;
  516.          coltab[numDN-i].r  = coltab[i-1].r;
  517.          coltab[i-1].r      = hold;
  518.  
  519.          hold               = coltab[numDN-i].g;
  520.          coltab[numDN-i].g  = coltab[i-1].g;
  521.          coltab[i-1].g      = hold;
  522.  
  523.          hold               = coltab[numDN-i].b;
  524.          coltab[numDN-i].b  = coltab[i-1].b;
  525.          coltab[i-1].b      = hold;
  526.     }
  527.  
  528.     WritePalette(coltab);
  529. }
  530.  
  531.  
  532. void ShowPalette( int numdiddle)
  533. {
  534.     int    samp, box, line, i;
  535.     int    numbox, DNperbox, boxns, boxnl;
  536.     unsigned char   PaletteLine[MAXDISPNS];
  537.  
  538. /*  Set up some constants */
  539.     numbox = min (numDN, numdiddle);
  540.     DNperbox = numDN / numbox;
  541.     boxns = dispns / numbox;
  542.     boxnl = dispnl / 10;
  543.     samp = 0;
  544.  
  545.     for (box = 0; box < numbox;  box++)
  546.         for (i = 0;  i < boxns; i++)
  547.             PaletteLine[samp++] = box*DNperbox;
  548.  
  549.     for (line = dispnl-boxnl;  line <= dispnl;  line++)
  550.         DisplayLine (PaletteLine, line, 1, numbox*boxns);
  551. }
  552.  
  553.  
  554. void ErasePalette( int numdiddle)
  555. {
  556.     int    samp, box, line, i;
  557.     int    numbox, DNperbox, boxns, boxnl;
  558.     unsigned char   PaletteLine[MAXDISPNS];
  559.  
  560. /*  Set up some constants */
  561.     numbox = min (numDN, numdiddle);
  562.     DNperbox = numDN / numbox;
  563.     boxns = dispns / numbox;
  564.     boxnl = dispnl / 10;
  565.     samp = 0;
  566.  
  567.     for (box = 0; box < numbox;  box++)
  568.         for (i = 0;  i < boxns; i++)
  569.             PaletteLine[samp++] = 0;
  570.  
  571.     for (line = dispnl-boxnl;  line <= dispnl;  line++)
  572.         DisplayLine (PaletteLine, line, 1, numbox*boxns);
  573. }
  574.