home *** CD-ROM | disk | FTP | other *** search
- #define SHOW_HIST /* def to show histo after key */
- #undef NO_INVERT /* def if black is 0xff */
- #define FLICKER /* def to test flicker thing. else just f-s */
- #define NEW_RANDOM /* def to new code to add random noise */
- #define SHOW_SCREENS /* def to display each screen slowly first */
- #define AUTO_SHOW /* def to automatically cycle then proceed */
-
- /*
- * this is for screen-switching on mono to simulate grayscale. it
- * uses a combination of floyd-steinberg and simulate "planes" which
- * get displayed each vblank. the image it works from should be
- * grayscale, i.e. each pixel is represented by an 8-bit (0 to 255)
- * intensity. since GIF images come with a color table, it is first
- * required to map each GIF pixel to the color table which has been
- * first changed to grayscale, either by averaging the rgb values
- * or by using the NTSC intensity equation.
- *
- * note that i think the f-s algorithm employed here sweeps each row
- * left to right rather than alternating directions. that is why there
- * is spurious info in areas otherwise supposed to be white.
- *
- * also, all points where chars are used in a calculation, they MUST
- * be unsigned.
- *
- * return ptr to screens.
- */
-
- /* written by Klaus Pedersen (micro@imada.dk) */
- /* modified by Bill Rosenkranz (rosenkra@convex.com) */
-
- static char *sccsid = "@(#) flicker.c 1.2 91/6/14 rosenkra\0\0 ";
-
- #include <stdio.h>
- #include <osbind.h>
-
- #ifdef LOCAL
- #undef LOCAL
- #endif
- #ifdef GLOBAL
- #undef GLOBAL
- #endif
-
- #define LOCAL /*static*/
- #define GLOBAL
- #define reg_t register
-
- #define LEVELS 4
- #define NUMERRS 1024
- #define SCRNSPACE 48256L
-
-
- /*
- * globals.
- *
- * these are the thresholds for quantizing. 0,85,170,255 seem best
- */
- LOCAL int _Levels[LEVELS] = { 0, 85, 170, 255};
-
- LOCAL int _Width; /* image size */
- LOCAL int _Hight;
- LOCAL int _Beta; /* for the Laplace filter */
- LOCAL int _MaxRandom; /* for adding random noise */
- LOCAL int *_Err1, /* the error propagation arrays */
- *_Err2;
- LOCAL int _Err1Array[NUMERRS],
- _Err2Array[NUMERRS];
- LOCAL int _ScrnBuf[SCRNSPACE], /* enuf for 3 screens... */
- *_Scrn,
- *_Scrn1,
- *_Scrn2,
- *_Scrn3;
- long _Hist[256]; /* histogram */
-
-
- /*
- * local functions
- */
- LOCAL void _Conv2Gray ();
- LOCAL void _SimpConv2Gray ();
- LOCAL int _GenConvPix ();
- LOCAL int _Laplace ();
- LOCAL void _ClearErr ();
- LOCAL int _Rand ();
- LOCAL int _Delay ();
- LOCAL int _DoHist ();
- LOCAL int _GetHist ();
-
-
-
- /*------------------------------*/
- /* flicker */
- /*------------------------------*/
- GLOBAL int *flicker (pimg, width, hight, beta, maxrandom, opt)
- unsigned char *pimg; /* -> raster image of intensities */
- int width; /* width, pixels */
- int hight; /* height, pixels */
- int beta; /* for laplace filter */
- int maxrandom; /* for random noise */
- int opt; /* 0=no flicker, 1=flicker */
- {
-
- /*
- * this is the main entry point. complete grayscale raster image
- * comes from pimg with height and width specified. if beta != 0,
- * do Laplace filter with that beta. if maxrandom != 0, add some
- * random noise with that value (see below).
- *
- * we return ptr to first screen. the other two immediately follow
- * it.
- */
-
- register long ii;
-
- /*
- * set our globals
- */
- _Hight = hight; /* its height... */
- _Width = width; /* ...and width */
- _Beta = beta; /* Laplace filter coefficient (fixedpoint: */
- /* 1=0.25, 2=0.50, 3=0.75... (Try 4) */
- _MaxRandom = maxrandom; /* amount of random noise on threshold value */
- /* (0 - 255) for 0% to 100% noise. (Try 10) */
-
- for (ii = 0L; ii < SCRNSPACE; ii++) /* clear screens! */
- _ScrnBuf[ii] = 0;
-
- #if 0
- printf ("\n\nwidth,height,beta,maxrandom = %d %d %d %d\n",
- _Width, _Hight, _Beta, _MaxRandom);
- printf ("pimg = %ld\nany key...\n", (long) pimg);
- _Delay (4000);
- if (Bconstat (2))
- {
- while (Bconstat (2))
- Bconin (2);
- exit (1);
- }
- #endif
-
- /*
- * do it!
- */
- if (opt)
- _Conv2Gray (pimg);
- else
- _SimpConv2Gray (pimg);
-
-
- /*
- * return ptr to screens (_Scrn is already page-aligned)...
- */
- return ((int *) _Scrn);
- }
-
-
-
-
- /*------------------------------*/
- /* _Conv2Gray */
- /*------------------------------*/
- LOCAL void _Conv2Gray (pic)
- unsigned char *pic;
- {
- register int *ps;
- register int *pd;
- register long ii;
- int i;
- register int x;
- int y;
- int w;
- int h;
- register long yoffset;
- int *TmpErr;
- register int q;
- int rover1;
- int rover2;
- register unsigned int pix;
- unsigned char *p;
- char *old1;
- char *old2;
-
-
-
- #ifdef SHOW_HIST
- /*
- * get histogram now. we do not do this in SimpConv...
- */
- _GetHist (pic, _Width, _Hight, _Hist);
- #endif
-
-
- /*
- * first clear the error arrays
- */
- _ClearErr ();
-
-
- /*
- * save old screen info, then set logbase to old physbase and
- * physbase to first screen buffer. we *should* never see logbase
- * in the displayed image since we never display logbase. make
- * sure screen is aligned on 256-byte boundary.
- */
- old1 = Logbase ();
- old2 = Physbase ();
- _Scrn = (int *) (((long) _ScrnBuf + 256L) & 0xFFFFFF00L);
- for (ii = 0L; ii < 32000L; ii++)
- {
- old1[ii] = 0;
- old2[ii] = 0;
- }
- Setscreen (old2, _Scrn, -1);
-
-
- /*
- * we set physbase to our buffer already so _Scrn1 points to it.
- * set the other screen pointers. _Scrn is a buffer large enuf
- * to hold all 3 screens
- */
- _Scrn1 = Physbase ();
- _Scrn2 = _Scrn1 + 16000L;
- _Scrn3 = _Scrn2 + 16000L;
-
-
- /*
- * initialize some things. yoffset positions us into each screen
- * which are int arrays. each scan line in the screen is thus
- * 40 words long.
- */
- yoffset = 0L;
- rover1 = 0;
- rover2 = 0;
-
-
- /*
- * loop over all rows in image
- */
- h = (_Hight > 400) ? 400 : _Hight;
- for (y = 1; y < h - 1; y++)
- {
- /*
- * set ptr to this pixel row
- */
- p = pic + ((long) y * (long) _Width);
-
- /*
- * loop over all pixels in the row
- */
- w = (_Width > 640) ? 640 : _Width;
- for (x = 0; x < w - 1; x++)
- {
- pix = (0x8000 >> (x & 0x000f));
-
- /*
- * get new pixel value, with f-s error. this is
- * actually an index into the _Levels array.
- */
- if (y & 1)
- q = _GenConvPix (p, (int) x, 0);
- else
- q = _GenConvPix (p, (int) x, 1);
-
-
- /*
- * set screen pixels based on this index
- */
- if (q == 1)
- {
- switch (rover1)
- {
- case 0:
- _Scrn1[yoffset + (x >> 4)] |= pix;
- rover1 = 1;
- rover2 = 1;
- break;
- case 1:
- _Scrn2[yoffset + (x >> 4)] |= pix;
- rover1 = 2;
- rover2 = 2;
- break;
- case 2:
- _Scrn3[yoffset + (x >> 4)] |= pix;
- rover1 = 0;
- rover2 = 0;
- break;
- }
- }
- else if (q == 2)
- {
- switch (rover2)
- {
- case 0:
- _Scrn1[yoffset + (x >> 4)] |= pix;
- _Scrn2[yoffset + (x >> 4)] |= pix;
- rover2 = 1;
- rover1 = 2;
- break;
- case 1:
- _Scrn2[yoffset + (x >> 4)] |= pix;
- _Scrn3[yoffset + (x >> 4)] |= pix;
- rover2 = 2;
- rover1 = 0;
- break;
- case 2:
- _Scrn1[yoffset + (x >> 4)] |= pix;
- _Scrn3[yoffset + (x >> 4)] |= pix;
- rover2 = 0;
- rover1 = 1;
- break;
- }
- }
- else if (q == 3)
- {
- _Scrn1[yoffset + (x >> 4)] |= pix;
- _Scrn2[yoffset + (x >> 4)] |= pix;
- _Scrn3[yoffset + (x >> 4)] |= pix;
- }
- }
-
-
- /*
- * get ready for next row by incrementing offset into
- * the screens (640 dots = 40 words)
- */
- yoffset += 40;
-
-
- /*
- * exchange error arrays
- */
- TmpErr = _Err1;
- _Err1 = _Err2;
- _Err2 = TmpErr;
-
-
- /*
- * check for early withdrawal...
- */
- if (Bconstat (2))
- {
- while (Bconstat (2))
- Bconin (2);
- #if 0
- Setscreen (old1, old2, -1);
- return;
- #else
- break; /* no return, display partial image */
- #endif
- }
- }
-
-
-
- /*
- * with that all done, now we can display the screens. only
- * phys screen is displayed (at next vblank). the Vsync waits
- * for the vblank. we display screens 1,2,3. any char stops the
- * loop. first just show the screens with delay, then do the loop
- */
- #ifdef SHOW_SCREENS
-
- # ifdef AUTO_SHOW
- /* automatically slow cycle thru screens */
- for (i = 0; i < 2; i++)
- {
- Setscreen (old2, _Scrn1, -1); Vsync (); _Delay (200);
- Setscreen (old2, _Scrn2, -1); Vsync (); _Delay (200);
- Setscreen (old2, _Scrn3, -1); Vsync (); _Delay (200);
-
- if (Bconstat (2)) goto autodone;
- }
- for (i = 0; i < 3; i++)
- {
- Setscreen (old2, _Scrn1, -1); Vsync (); _Delay (100);
- Setscreen (old2, _Scrn2, -1); Vsync (); _Delay (100);
- Setscreen (old2, _Scrn3, -1); Vsync (); _Delay (100);
-
- if (Bconstat (2)) goto autodone;
- }
- for (i = 0; i < 4; i++)
- {
- Setscreen (old2, _Scrn1, -1); Vsync (); _Delay (50);
- Setscreen (old2, _Scrn2, -1); Vsync (); _Delay (50);
- Setscreen (old2, _Scrn3, -1); Vsync (); _Delay (50);
-
- if (Bconstat (2)) goto autodone;
- }
- for (i = 0; i < 6; i++)
- {
- Setscreen (old2, _Scrn1, -1); Vsync (); _Delay (20);
- Setscreen (old2, _Scrn2, -1); Vsync (); _Delay (20);
- Setscreen (old2, _Scrn3, -1); Vsync (); _Delay (20);
-
- if (Bconstat (2)) goto autodone;
- }
-
- # else /*!AUTO_SHOW*/
-
- do
- {
- Setscreen (old2, _Scrn1, -1); Vsync (); _Delay (200);
- Setscreen (old2, _Scrn2, -1); Vsync (); _Delay (200);
- Setscreen (old2, _Scrn3, -1); Vsync (); _Delay (200);
-
- } while (!Bconstat (2));
-
- # endif /*AUTO_SHOW*/
-
- autodone:
- /* clear any key presses */
- while (Bconstat (2))
- Bconin (2);
-
- #endif /*SHOW_SCREENS*/
-
-
- /*
- * show screens at speed. wait for keypress...
- */
- do
- {
- Setscreen (old2, _Scrn1, -1); Vsync ();
- Setscreen (old2, _Scrn2, -1); Vsync ();
- Setscreen (old2, _Scrn3, -1); Vsync ();
-
- } while (!Bconstat (2));
-
-
-
-
- #ifdef SHOW_HIST
-
- /* clear any key presses */
- while (Bconstat (2))
- Bconin (2);
-
- /*
- * show histogram on screen, too, with image. note that _DoHist
- * uses line A to draw to screen (logical, i think) so we set
- * screen to make sure the histo gets on the screen.
- */
- Setscreen (_Scrn1, _Scrn1, -1); Vsync ();
- _DoHist (_Scrn1, _Hist, 1);
- Setscreen (_Scrn2, _Scrn2, -1); Vsync ();
- _DoHist (_Scrn2, _Hist, 2);
- Setscreen (_Scrn3, _Scrn3, -1); Vsync ();
- _DoHist (_Scrn3, _Hist, 3);
-
-
- do
- {
- Setscreen (old2, _Scrn1, -1); Vsync ();
- Setscreen (old2, _Scrn2, -1); Vsync ();
- Setscreen (old2, _Scrn3, -1); Vsync ();
-
- } while (!Bconstat (2));
-
-
- /*
- * make sure to undo the change!
- */
- _DoHist (_Scrn1, _Hist, -1);
- _DoHist (_Scrn2, _Hist, -2);
- _DoHist (_Scrn3, _Hist, -3);
- #endif
-
-
-
- /*
- * before resetting screen and returning, copy a screen to orig
- * physbase
- */
- ps = (int *) _Scrn1;
- pd = (int *) old2;
- for (ii = 0L; ii < 16000L; ii++)
- *pd++ = *ps++;
-
-
- /*
- * reset screens back to what they were
- */
- Setscreen (old1, old2, -1);
-
-
- /*
- * clear any waiting keys...
- */
- while (Bconstat (2))
- Bconin (2);
- }
-
-
-
-
- /*------------------------------*/
- /* _SimpConv2Gray */
- /*------------------------------*/
- LOCAL void _SimpConv2Gray (pic)
- unsigned char *pic;
- {
-
- /*
- * I have also made a version of "Convert2Gray", that don't use
- * flicker - this allows the pictures to be saved, and used in windows,
- * and honest - the build-in test-picture looks as good, or even better,
- * without the flicker... (this is not true for any *real* pictures
- * that I have tested the program with). Here it is :
- */
-
- long x,
- y,
- yoffset,
- wordpos;
- int w,
- h;
- int *TmpErr;
- unsigned int pix;
- unsigned char *p;
-
-
-
- /*
- * first clear the error arrays
- */
- _ClearErr ();
-
-
- /*
- * there is only one screen. we use existing physbase
- */
- _Scrn1 = Physbase ();
-
-
- /*
- * yoffset positions us into the screen which is an int arrays.
- * each scan line in the screen is thus 40 words long.
- */
- yoffset = 0;
- pix = 0;
-
-
- /*
- * loop over all rows in image
- */
- h = (_Hight > 400) ? 400 : _Hight;
- for (y = 1; y < h - 1; y++)
- {
- /*
- * set ptr to this pixel row
- */
- p = pic + ((long) y * (long) _Width);
- wordpos = yoffset;
-
-
- /*
- * loop over all pixels in the row
- */
- w = (_Width > 640) ? 640 : _Width;
- for (x = 0L; x < w - 1; x++)
- {
- pix <<= 1;
- if (_GenConvPix (p, (int) x, 0))
- pix++;
- if ((x & 0xf) == 0xf)
- _Scrn1[wordpos++] = pix;
- }
-
-
- /*
- * get ready for next row by incrementing offset into
- * the screens (640 dots = 40 words)
- */
- yoffset += 40;
-
-
- /*
- * exchange error arrays
- */
- TmpErr = _Err1;
- _Err1 = _Err2;
- _Err2 = TmpErr;
-
-
- /*
- * check for early withdrawal...
- */
- if (Bconstat (2))
- {
- while (Bconstat (2))
- Bconin (2);
- #if 0
- return;
- #else
- break; /* display partial image */
- #endif
- }
- }
-
- /*
- * displaying the image consists of waiting for a char since we
- * already drew it to the screen. so just return. let caller
- * do any waiting...
- */
- #if 0
- while (!Bconstat(2))
- ;
- while (Bconstat (2))
- Bconin (2);
- #endif
- }
-
-
-
-
- /*------------------------------*/
- /* _GenConvPix */
- /*------------------------------*/
- LOCAL int _GenConvPix (pic, x, opt)
- unsigned char *pic; /* -> image pixel array */
- int x; /* the current pixel */
- int opt; /* 0=l to r, 1=r to l */
- {
-
- /*
- * This rutine converts a point in the 'real' image to
- * a point in the screen image. The procedure uses error-
- * diffusion to determine the state of the new pixel.
- * The Error filter is that of Floyd & Steinberg :
- *
- * / 1 5 3 \ /
- * \ 7 X / / 16
- *
- * This rutine uses a table of levels to make the convertion.
- *
- * It returns the index for the pixel from the quantizing Level
- * array, i.e. the new pixel intensity is Level[i].
- */
-
- register int *p_levels;
- register int p;
- register int e;
- register int i;
- register int err;
- int lev;
-
-
- p_levels = _Levels;
-
-
- #ifdef NEW_RANDOM
- /*
- The noise is here added to the picture, this means that the noise
- isn't cancled out again, and that is NOT intended, the noise should
- only act as some kind of *catalysator* (verb. is stolen from
- chemistry - something that start a reaction). The correct way to add
- noise is :
- */
-
- /*
- * first do the weighted average. _Err1 is the current line,
- * _Err2 is the previous line.
- */
- if (x == 0)
- {
- # ifdef NO_INVERT
- /*!!! next line was actually: */
-
- p = *pic;
-
- /*!!! but that inverted the image. it was assumed that 0xff was black.
- we insist that black is 0x00 (low intensity) */
- # else
- p = 255 - *pic;
- # endif
- }
- else if (_Beta)
- {
- p = ((7*_Err1[x - 1]
- + _Err2[x - 1] + 5*_Err2[x] + 3*_Err2[x + 1]) >> 4)
- + _Laplace (pic + x);
- }
- else
- {
- p = ((7*_Err1[x - 1]
- + _Err2[x - 1] + 5*_Err2[x] + 3*_Err2[x + 1]) >> 4)
- # ifdef NO_INVERT
- + *(pic + x);
- # else
- + (255 - *(pic + x));
- # endif
- }
-
-
- /*
- * now calculate the residual errors
- */
- err = NUMERRS;
- for (i = 0; i < LEVELS; i++)
- {
- if (_MaxRandom)
- e = p + _Rand (_MaxRandom) - p_levels[i];
- else
- e = p - p_levels[i];
-
- if (e < 0)
- e = -e;
- if (e < err)
- {
- err = e;
- lev = i;
- }
- }
- _Err1[x] = p - p_levels[lev];
-
- #else /*!NEW_RANDOM*/
-
- if (x == 0)
- {
- # ifdef NO_INVERT
- p = *pic;
- # else
- p = 255 - *pic;
- # endif
- }
- else if (_Beta)
- {
- if (_MaxRandom)
- p = ((7 * _Err1[x - 1] + _Err2[x - 1]
- + 5 * _Err2[x] + 3 * _Err2[x + 1]) >> 4)
- + _Laplace (pic + x) + _Rand (_MaxRandom);
- else
- p = ((7 * _Err1[x - 1] + _Err2[x - 1]
- + 5 * _Err2[x] + 3 * _Err2[x + 1]) >> 4)
- + _Laplace (pic + x);
- }
- else
- {
- if (_MaxRandom)
- {
- p = ((7 * _Err1[x - 1] + _Err2[x - 1]
- + 5 * _Err2[x] + 3 * _Err2[x + 1]) >> 4)
- # ifdef NO_INVERT
- + *(pic + x) + _Rand (_MaxRandom);
- # else
- + (255 - *(pic + x)) + _Rand (_MaxRandom);
- # endif
- }
- else
- {
- p = ((7 * _Err1[x - 1] + _Err2[x - 1]
- + 5 * _Err2[x] + 3 * _Err2[x + 1]) >> 4)
- # ifdef NO_INVERT
- + *(pic + x);
- # else
- + (255 - *(pic + x));
- # endif
- }
- }
- err = NUMERRS;
- for (i = 0; i < LEVELS; i++)
- {
- e = p - p_levels[i];
- if (e < 0)
- e = -e;
- if (e < err)
- {
- err = e;
- lev = i;
- }
- }
- _Err1[x] = p - p_levels[lev];
-
- #endif /*NEW_RANDOM*/
-
- return (lev);
- }
-
-
-
-
- /*------------------------------*/
- /* _Laplace */
- /*------------------------------*/
- LOCAL int _Laplace (Pic)
- unsigned char *Pic;
- {
-
- /*
- * this is a Laplacian filter, a simple edge detector/enhancer.
- *
- * -1
- * -1 4 -1
- * -1
- */
-
- register unsigned char *pc;
- register int lp;
- register int b;
- register int w;
-
-
- pc = Pic;
- b = _Beta;
- w = _Width;
-
-
-
- /*
- * if _Beta 0, formula reduces to just the pixel
- */
- #ifdef NO_INVERT
- if (b == 0)
- return ((int) *pc);
-
- lp = (*pc << 2) /* this pixel */
- - *(pc - 1) - *(pc + 1) /* left/right */
- - *(pc + w) - *(pc - w); /* top/bottom */
- lp = ((b * lp) >> 2) + *pc;
- #else
- if (b == 0)
- return ((int) (255 - *pc));
-
- lp = (255 - *pc) << 2; /* this pixel */
- lp -= (255 - *(pc - 1)); /* left/right */
- lp -= (255 - *(pc + 1));
- lp -= (255 - *(pc + w)); /* top/bottom */
- lp -= (255 - *(pc - w));
- lp = ((b * lp) >> 2);
- lp += (255 - *pc); /* self */
- #endif
-
- /*
- * check limits and force result to 8 bits
- */
- if (lp < 0)
- lp = 0;
- if (lp > 255)
- lp = 255;
-
- return (lp);
- }
-
-
-
-
- /*------------------------------*/
- /* _ClearErr */
- /*------------------------------*/
- LOCAL void _ClearErr ()
- {
- register int i;
- register int w;
- register int *pe1;
- register int *pe2;
-
-
- _Err1 = _Err1Array;
- _Err2 = _Err2Array;
-
- pe1 = _Err1Array;
- pe2 = _Err2Array;
- w = _Width;
- for (i = 0; i < w; i++)
- {
- *pe1++ = 0;
- *pe2++ = 0;
- }
- }
-
-
-
-
- /*------------------------------*/
- /* _Rand */
- /*------------------------------*/
- LOCAL int _Rand (mx)
- int mx;
- {
-
- /*
- * returns random number 0 <= x < mx
- */
-
- static long Seed = 0;
-
- if (mx == 0)
- return (0);
-
- /* Seed = (5 * Seed + 37);*/
- Seed += (Seed << 2) + 37; /* same thing but faster */
- /* Seed &= 0x00ffffffL;*/ /* should prevent overflow */
-
- return (((int) Seed) % mx);
- }
-
-
-
-
- /*------------------------------*/
- /* _Delay */
- /*------------------------------*/
- LOCAL _Delay (ms)
- int ms;
- {
- /*
- * delay with 1 ms granularity on normal ST
- */
- int i;
- for ( ; ms > 0; ms--) for (i = 192; i > 0; i--) ;
- }
-
-
-
-
- /*------------------------------*/
- /* _GetHist */
- /*------------------------------*/
- _GetHist (pras, w, h, hist)
- unsigned char *pras;
- int w;
- int h;
- long *hist;
- {
- long x;
- long y;
- register long ii;
- register long lim;
- register unsigned char *ps;
- register long *ph;
- register unsigned int hval; /* ptr into Hist */
-
-
- /*
- * clear histo
- */
- for (ph = hist, ii = 0L; ii < 256; ii++)
- *ph++ = 0L;
-
- /*
- * do it...
- */
- lim = (long) h * (long) w;
- for (ph = hist, ps = pras, ii = 0L; ii < lim; ii++, ps++)
- {
- hval = (unsigned int) *ps;
- ph[hval] += 1;
- }
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* _DoHist */
- /*------------------------------*/
-
- int _save1[260*4]; /* NOTE: change dims if hist size changes!!! */
- int _save2[260*4];
- int _save3[260*4];
-
- _DoHist (scrn, hst, opt)
- int *scrn;
- long *hst;
- int opt;
- {
-
- /*
- * draw a histogram, vertical axis, horizontal values.
- */
-
- register int *psav;
- register long *phst;
- register int *pscrn;
- int xmn;
- int ymn;
- int xmx;
- int ymx;
- int vspace;
- int barsize;
- register long hmax;
- register int hstsiz;
- int bordr;
-
- register int i;
- register int j;
- int x1,
- x2,
- y1,
- y2;
- long xsz;
-
-
- /*
- * set sizes, location
- */
- hstsiz = 256;
- vspace = 1;
- barsize = 1;
- xmn = 560;
- ymn = 16;
- xmx = xmn+64;
- ymx = ymn+256;
- bordr = 2;
-
-
- /*
- * are we drawing histo or restoring the screen?
- */
- if (opt > 0)
- {
- /*
- * drawing. find max value...
- */
- for (hmax = 0, phst = hst, i = 0; i < hstsiz; i++, phst++)
- {
- if (*phst > hmax)
- hmax = *phst;
- }
-
-
- /*
- * make space for histogram. save the part of the screen
- * we clobber, too.
- */
- switch (opt)
- {
- case 1: psav = _save1; break;
- case 2: psav = _save2; break;
- case 3: psav = _save3; break;
- }
- pscrn = scrn;
- for (j = ymn; j < ymx; j++)
- {
- for (i = xmn/16; i < xmx/16; i++)
- {
- *psav++ = pscrn[(j-1)*40 + i];
- pscrn[(j-1)*40 + i] = 0;
- }
- }
-
-
- #if 0
- /*
- * draw box around histogram
- */
- do_line (xmn-bordr, ymn-bordr, xmx+bordr, ymn-bordr);
- do_line (xmn-bordr, ymn-bordr, xmn-bordr, ymx+bordr);
- do_line (xmx+bordr, ymx+bordr, xmx+bordr, ymn-bordr);
- do_line (xmx+bordr, ymx+bordr, xmn-bordr, ymx+bordr);
- #endif
-
- /*
- * draw the lines. note that a "baseline" could appear
- * because for hst entries of 0, the line is just a dot
- * so we do not draw these.
- */
- xsz = (long) (xmx - xmn);
- for (i = 0; i < hstsiz; i++)
- {
- x1 = xmn;
- y1 = ymn + (i * vspace);
- x2 = x1 + (int) ((xsz * hst[i]) / hmax);
- y2 = y1;
- if (x2 - x1 > 0)
- {
- for (j = 0; j < barsize; j++, y1++, y2++)
- do_line (x1, y1, x2, y2);
- }
- }
- }
- else
- {
- /*
- * restore the part of the screen the histo clobbered...
- */
- switch (opt)
- {
- case -1: psav = _save1; break;
- case -2: psav = _save2; break;
- case -3: psav = _save3; break;
- }
- pscrn = scrn;
- for (j = ymn; j < ymx; j++)
- {
- for (i = xmn/16; i < xmx/16; i++)
- {
- pscrn[(j-1)*40 + i] = *psav++;
- }
- }
- }
- }
-
-
-
-
-
-