#define V_HIST /* def for vertical histogram */ #undef DBL_LOOP /* def for for(x..., for(y... loops */ #undef FULL_SCREEN /* def to write entire screen, not just wxh */ /* * low.c - low level stuff for mgif. */ static char *sccsid = "@(#) low.c 1.0 91/6/14 rosenkra\0\0 "; #include #include #include "mgif.h" /* * globals */ extern int Batch; /* * local functions */ int do_hist (); int draw_hist (); int drhhist (); int drvhist (); int grid (); int do_line (); /* atari ST (line A) */ void xor_line (); void xor_dash (); /* atari ST (line A) */ int cursor (); /* atari ST (gemdos, vt52) */ int clr_cmd (); /* atari ST (gemdos, vt52) */ int mv_cursor (); /* atari ST (vt52) */ int clr_screen (); /* atari ST (gemdos, vt52) */ long do_time (); /* atari ST (gemdos, sysvar) */ int check_key (); /* atari ST (BIOS) */ int get_key (); int get_string (); long get_rkey (); int get_xypos (); int wait_key (); /* atari ST (BIOS) */ int wait_ms (); /*------------------------------*/ /* do_hist */ /*------------------------------*/ do_hist (pras, w, h, hist) uchar_t *pras; int w; int h; long *hist; { long x; long y; register long ii; register long lim; register uchar_t *ps; register long *ph; register uint_t hval; /* ptr into Hist */ for (ph = hist, ii = 0L; ii < HISTSIZ; ii++) *ph++ = 0L; #ifdef DBL_LOOP for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { hval = (uint_t) (pras[(y*w) + x]); hist[hval] += 1; } } #else lim = (long) h * (long) w; for (ph = hist, ps = pras, ii = 0L; ii < lim; ii++, ps++) { hval = (uint_t) *ps; ph[hval] += 1; } #endif return (1); } /*------------------------------*/ /* draw_hist */ /*------------------------------*/ int draw_hist (hist) long *hist; { /* * draw histogram */ long hmax; int x1, x2, y1, y2; long htot; long ii; /* * find max values in histo for scaling. also total pixels (should * be w*h) */ for (htot = 0, hmax = 0, ii = 0; ii < HISTSIZ; ii++) { htot += hist[ii]; if (hist[ii] > hmax) hmax = hist[ii]; } /* * overall histogram... */ #ifdef V_HIST x1 = 100; y1 = 88; x2 = x1 + HISTSIZ; y2 = y1 + 208; drvhist (hist, HISTSIZ, hmax, x1, y1, x2, y2, 4, 1, 1); mv_cursor ( 0, 19); printf (" 00 FF"); mv_cursor ( 0, 5); printf (" %6ld", hmax); mv_cursor ( 0, 18); printf (" 0"); #else x1 = 100; y1 = 50; x2 = x1 + 400; y2 = y1 + HISTSIZ; drhhist (hist, HISTSIZ, hmax, x1, y1, x2, y2, 4, 1, 1); mv_cursor ( 0, 3); printf (" 00"); mv_cursor ( 0, 19); printf (" FF"); #endif /* * legends */ mv_cursor ( 1, 1); printf (" Histogram for this image:"); mv_cursor ( 1, 22); printf (" Total pixels %ld", htot); } /*------------------------------*/ /* drhhist */ /*------------------------------*/ int drhhist (hst, hstsiz, hmax, xmn, ymn, xmx, ymx, bordr, vspace, barsize) long *hst; int hstsiz; long hmax; int xmn; int ymn; int xmx; int ymx; int bordr; int vspace; int barsize; { /* * draw a histogram, vertical axis, horizontal values. UL/LR corners * specified (pixel coord). border outside the corners if bordr >= 0. * vert spacing (in pixels) given by vspace. if hmax is > 0, scale * the length to this value, otherwise automatically scale to fit. * * ____________________________________________ * | /----- start here: (xmn,ymn) |<-- border, drawn * | +XXXXXXXXXXXXXXXXXXXXXXXXX | if bordr >= 0 * | XXXXXXXXX | * | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | * | XXXXXXXXXXXXXXXXXXX | * . . * . . * . . * | XXXXXXXXXXXXX | * | XXXXXXXXXXXXXXXXXXXXXXXXX + | * |____________________________________________| * * width of each bar given by barsize (in pixels). vspace should include * barsize: * * XXXXXXXXXXXXXXXXXXXXXX ------------------------------------------ * XXXXXXXXXXXXXXXXXXXXXX barsize(=3) * XXXXXXXXXXXXXXXXXXXXXX ---------------------------- vspace(=4) * * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--------------------------------- * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ int i; int j; int x1, x2, y1, y2; long xsz; /* * check data... */ if (vspace < 1) vspace = 1; if ((vspace * hstsiz) > (ymx - ymn + 1)) vspace = (ymx - ymn) / hstsiz; if (vspace < 1) return; if (barsize > vspace) barsize = vspace; /* * find max value if necessary... */ if (hmax < 0) { hmax = 0; for (i = 0; i < hstsiz; i++) { if (hst[i] > hmax) hmax = hst[i]; } } /* * draw box around histogram */ if (bordr >= 0) { 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); } /* * 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); } } } /*------------------------------*/ /* drvhist */ /*------------------------------*/ int drvhist (hst, hstsiz, hmax, xmn, ymn, xmx, ymx, bordr, hspace, barsize) long *hst; int hstsiz; long hmax; int xmn; int ymn; int xmx; int ymx; int bordr; int hspace; int barsize; { /* * draw a histogram, horizontal axis, vertical values. UL/LR corners * specified (pixel coord). border outside the corners if bordr >= 0. * vert spacing (in pixels) given by hspace. if hmax is > 0, scale * the length to this value, otherwise automatically scale to fit. * * _________ . . . _____ * | X |<-- border, drawn * | X X X | if bordr >= 0 * | XX X X | * | XX X X | * | X XXX X XX | * | X XXX X XXX | * | X XXXXX XXX | * | +XXXXXX XXXX | * | \-- start here: | * | (xmn,ymn) | * |_________ . . . _____| * * width of each bar given by barsize (in pixels). hspace should include * barsize: * * /-------- barsize(=3) * | /---- hspace(=4) * | | | | | * | | | v | * | | |<->| * | | | | * | ||| || * | v|| || * |<>|| || * | || || * XXX | || * XXX | || * XXX | |XXX * XXX | |XXX * XXX XXX XXX * XXX XXX XXX * XXX XXX XXX */ int i; int j; int x1, x2, y1, y2; long ysz; /* * check data... */ if (hspace < 1) hspace = 1; if ((hspace * hstsiz) > (xmx - xmn + 1)) hspace = (xmx - xmn) / hstsiz; if (hspace < 1) return; if (barsize > hspace) barsize = hspace; /* * find max value if necessary... */ if (hmax < 0) { hmax = 0; for (i = 0; i < hstsiz; i++) { if (hst[i] > hmax) hmax = hst[i]; } } /* * draw box around histogram */ if (bordr >= 0) { 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); } /* * 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. */ ysz = (long) (ymx - ymn); for (i = 0; i < hstsiz; i++) { y1 = ymx; y2 = y1 - (int) ((ysz * hst[i]) / hmax); x1 = xmn + (i * hspace); x2 = x1; if (y1 - y2 > 0) { for (j = 0; j < barsize; j++, x1++, x2++) do_line (x1, y1, x2, y2); } } } /*------------------------------*/ /* grid */ /*------------------------------*/ grid (x, y, w, h, sp) int x; int y; int w; int h; int sp; { int i; /* * limit the grid so as not to go off screen! else line A will * crash... */ if (x < 0) x = 0; if (y < 0) y = 0; if (x+w >= 640) w = 640 - x - 1; if (y+h >= 400) h = 400 - y - 1; /* * verticals */ for (i = x; i < x+w; i += sp) xor_dash (i, y, i, y+h-1); /* last (right) one */ xor_dash (x+w-1, y, x+w-1, y+h-1); /* * horizontals */ for (i = y; i < y+h; i += sp) xor_dash (x, i, x+w-1, i); /* last (bottom) one */ xor_dash (x, y+h-1, x+w-1, y+h-1); } /*------------------------------*/ /* do_line */ /*------------------------------*/ do_line (x1, y1, x2, y2) int x1, y1, x2, y2; { /* * draw a line from (x1,y1) to (x2,y2). uses line A */ extern long linea0 (); extern int linea3 (); static long A_ptr = 0L; /* * line A init first, if needed */ if (!A_ptr) A_ptr = linea0 (); linea3 (A_ptr, x1, y1, x2, y2, 0, 0xFFFF, 0); } /*------------------------------*/ /* xor_line */ /*------------------------------*/ void xor_line (x1, y1, x2, y2) int x1, y1, x2, y2; { /* * draw a line from (x1,y1) to (x2,y2), XOR. uses line A */ extern long linea0 (); extern int linea3 (); static long A_ptr = 0L; /* * line A init first, if needed */ if (!A_ptr) A_ptr = linea0 (); linea3 (A_ptr, x1, y1, x2, y2, 2, 0xffff, 0); } /*------------------------------*/ /* xor_dash */ /*------------------------------*/ void xor_dash (x1, y1, x2, y2) int x1, y1, x2, y2; { /* * draw a line from (x1,y1) to (x2,y2), XOR. uses line A */ extern long linea0 (); extern int linea3 (); static long A_ptr = 0L; /* * line A init first, if needed */ if (!A_ptr) A_ptr = linea0 (); linea3 (A_ptr, x1, y1, x2, y2, 2, 0x3333, 0); } /*------------------------------*/ /* cursor */ /*------------------------------*/ cursor (visible) int visible; { /* * turn cursor on/off */ if (visible) Cconws ("\33e"); else Cconws ("\33f"); } /*------------------------------*/ /* clr_cmd */ /*------------------------------*/ clr_cmd () { /* * clear "command" line */ mv_cursor (0, 24); Cconws ("\33K"); } /*------------------------------*/ /* mv_cursor */ /*------------------------------*/ mv_cursor (col, row) int col; int row; { /* * move cursor to row,col (0,0 is UL corner). for printing */ int esc = 0x1B; int spc = 0x20; char msg[10]; sprintf (msg, "%cY%c%c\0", (char) esc, (char) (row + spc), (char) (col + spc)); Cconws (msg); } /*------------------------------*/ /* clr_screen */ /*------------------------------*/ clr_screen () { /* * clear screen, home cursor */ Cconws ("\33E"); } /*------------------------------*/ /* do_time */ /*------------------------------*/ long do_time (opt) int opt; /* 0=init,1=start,2=end (ret elapsed)*/ { /* * timing functions. here we time using 200 Hz system timer */ static ulong_t start; static ulong_t stop; long savessp; ulong_t elapsed; /* seconds */ switch (opt) { case 0: /* reset clock */ case 1: /* start clock */ savessp = Super (0L); start = *(long *) (0x4ba); Super (savessp); break; case 2: /* stop and elapsed */ savessp = Super (0L); stop = *(long *) (0x4ba); Super (savessp); if (stop < start) elapsed = (long) (stop - start + 0x7FFFFFFFL) / 200L; else elapsed = (long) (stop - start) / 200L; return ((long) elapsed); } return (0L); } /*------------------------------*/ /* check_key */ /*------------------------------*/ int check_key () { /* * ckecks for a key and flushes keyboard buffer. */ if (Bconstat (2)) /* if CONSOLE has a char... */ { while (Bconstat (2)) /* read char while there are */ Bconin (2); /* chars to read (flush) */ return (1); /* yes, there was a key */ } return (0); /* no key */ } /*------------------------------*/ /* get_key */ /*------------------------------*/ int get_key () { /* * gets a key. just the ascii part of Bconin. only low byte is filled. */ long ret; cursor (1); while (!Bconstat (2)) /* wait for a key... */ ; ret = Bconin (2) & 0x000000ffL;/* get key */ cursor (0); return ((int) ret); } /*------------------------------*/ /* get_string */ /*------------------------------*/ get_string (n, buf) int n; /* <= 125 */ char *buf; { int i; uint_t num; if (n > 125) n = 125; buf[0] = (char) n; cursor (1); Cconrs (buf); cursor (0); num = (uint_t) buf[1]; for (i = 0; i < num; i++) buf[i] = buf[i+2]; buf[num] = '\0'; } /*------------------------------*/ /* get_rkey */ /*------------------------------*/ long get_rkey () { /* * gets a key. the full long is returned */ long ret; while (!Bconstat (2)) /* wait for a key... */ ; ret = Bconin (2); /* get key */ return ((long) ret); } /*------------------------------*/ /* get_xypos */ /*------------------------------*/ int get_xypos (opt, type, xorg, yorg, width, height, rwidth, rheight, xstart, ystart, x, y) int opt; /* 0=vert(hor pos), 1=horiz(vert pos), 2=both */ int type; /* 0=xhair, 1=box */ int xorg; /* UL of limit rect */ int yorg; int width; /* size of limit rect */ int height; int rwidth; /* size of rect if type=box */ int rheight; int xstart; /* start position */ int ystart; int *x; /* returned coords */ int *y; { /* * draw crosshair or box, let user move with arrow (8 pixel) or * shift-arrows (1 pixel) and return final x,y. return value is as * follows: * * if INSERT * ret = 1 * else * ret = 0 * * space to confine cursor/box to is defined by xorg, yorg, width, height. * coord of last point returned in x,y no matter how we exit. crosshair * starts at (xstart,ystart). ClrHome moves to xorg,yorg, shift-ClrHome * moves to (xstart,ystart). box specified with xstart,ystart,rwidth, * rheight. */ register long lkey; register int drawit; register int xpos; register int ypos; int xrlim, xllim; int yulim, yllim; int i; int done; int ret; /* * check for bad input... */ if (width > 640) width = 640; if (height > 400) height = 400; if ((width < 2) || (height < 2)) return (0); if ((xorg < 0) || (xorg >= 640)) return (0); if ((yorg < 0) || (yorg >= 400)) return (0); if ((xorg + width - 1 > 640) || (yorg + height - 1 > 400)) return (0); if ((xstart > xorg + width - 1) || (xstart < xorg)) return (0); if ((ystart > yorg + height - 1) || (ystart < yorg)) return (0); /* * set start positions and limits */ xpos = xstart; ypos = ystart; if (type == 0) { xllim = xorg; xrlim = xllim + (width-1); yulim = yorg; yllim = yorg + (height-1); } else { xllim = xorg; xrlim = xllim + (rwidth-1); yulim = yorg; yllim = yorg + (rheight-1); } /* * draw initial position crosshair (xor mode)... */ if (type == 0) { switch (opt) { case H_COORD: xor_line (xpos,yulim,xpos,yllim); /* vert */ break; case V_COORD: xor_line (xllim,ypos,xrlim,ypos); /* horiz */ break; case VH_COORD: xor_line (xpos,yulim,xpos,yllim); /* vert */ xor_line (xllim,ypos,xrlim,ypos); /* horiz */ break; default: return (0); break; } } else { xor_line (xpos,ypos,xpos,ypos+rheight-1); xor_line (xpos,ypos,xpos+rwidth-1,ypos); xor_line (xpos,ypos+rheight-1,xpos+rwidth-1,ypos+rheight-1); xor_line (xpos+rwidth-1,ypos,xpos+rwidth-1,ypos+rheight-1); } /* * directions (on cmd line) */ mv_cursor (0,24); printf ("ARROWS 8 pix, Shift-ARROWS 1 pix. INSERT detects, any other quit. "); /* * loop... */ done = 0; ret = 0; while (!done) { /* * get raw key, update coord on screen... */ mv_cursor (70,24); printf ("%3d,%3d", xpos, ypos); lkey = get_rkey (); #if 0 mv_cursor (70,23); printf ("%08lx", lkey); #endif /* * undraw... */ if (type == 0) { switch (opt) { case H_COORD: xor_line (xpos,yulim,xpos,yllim); /* vert */ break; case V_COORD: xor_line (xllim,ypos,xrlim,ypos); /* horiz */ break; case VH_COORD: xor_line (xpos,yulim,xpos,yllim); /* vert */ xor_line (xllim,ypos,xrlim,ypos); /* horiz */ break; } } else { xor_line (xpos,ypos,xpos,ypos+rheight-1); xor_line (xpos,ypos,xpos+rwidth-1,ypos); xor_line (xpos,ypos+rheight-1,xpos+rwidth-1,ypos+rheight-1); xor_line (xpos+rwidth-1,ypos,xpos+rwidth-1,ypos+rheight-1); } /* * what key? */ if (lkey == RARROW) /* right arrow */ { /* * some arrows not used for some opts, so check */ if (opt != V_COORD) { /* * bump it and check if beyond limit */ xpos += 8; if (xpos > xrlim) { /* * if so, limit and bell */ xpos = xrlim; Cconws ("\07"); } } } else if (lkey == S_RARRAW) /* shift right arrow */ { if (opt != V_COORD) { xpos += 1; if (xpos > xrlim) { xpos = xrlim; Cconws ("\07"); } } } else if (lkey == LARRAW) /* left arrow */ { if (opt != V_COORD) { xpos -= 8; if (xpos < xllim) { xpos = xllim; Cconws ("\07"); } } } else if (lkey == S_LARRAW) /* shift left arrow */ { if (opt != V_COORD) { xpos -= 1; if (xpos < xllim) { xpos = xllim; Cconws ("\07"); } } } else if (lkey == UARRAW) /* up arrow */ { if (opt != H_COORD) { ypos -= 8; if (ypos < yulim) { ypos = yulim; Cconws ("\07"); } } } else if (lkey == S_UARRAW) /* shift up arrow */ { if (opt != H_COORD) { ypos -= 1; if (ypos < yulim) { ypos = yulim; Cconws ("\07"); } } } else if (lkey == DARRAW) /* down arrow */ { if (opt != H_COORD) { ypos += 8; if (ypos > yllim) { ypos = yllim; Cconws ("\07"); } } } else if (lkey == S_DARRAW) /* shift down arrow */ { if (opt != H_COORD) { ypos += 1; if (ypos > yllim) { ypos = yllim; Cconws ("\07"); } } } else if (lkey == INSERT) { ret = 1; done = 1; /* mv_cursor (70,23); printf ("INSERT ", lkey);*/ } else if (lkey == CLRHOME) { /* * move to org point */ xpos = xorg + 3; ypos = yorg + 3; /* mv_cursor (70,23); printf ("CLRHOME ", lkey);*/ } else if (lkey == S_CLRHOME) { /* * move to start point */ xpos = xstart; ypos = ystart; /* mv_cursor (70,23); printf ("S_CLRHOM", lkey);*/ } #if 0 else if (lkey == S_INSERT) { mv_cursor (70,23); printf ("S_INSERT", lkey); } else if (lkey == HELP) { mv_cursor (70,23); printf ("HELP ", lkey); } else if (lkey == UNDO) { mv_cursor (70,23); printf ("UNDO ", lkey); } #endif else { /* * any other key causes us to quit... */ done = 1; } /* * check for exit condition... */ if (done) break; /* * draw new postion */ if (type == 0) { switch (opt) { case H_COORD: xor_line (xpos,yulim,xpos,yllim); /* vert */ break; case V_COORD: xor_line (xllim,ypos,xrlim,ypos); /* horiz */ break; case VH_COORD: xor_line (xpos,yulim,xpos,yllim); /* vert */ xor_line (xllim,ypos,xrlim,ypos); /* horiz */ break; } } else { xor_line (xpos,ypos,xpos,ypos+rheight-1); xor_line (xpos,ypos,xpos+rwidth-1,ypos); xor_line (xpos,ypos+rheight-1,xpos+rwidth-1,ypos+rheight-1); xor_line (xpos+rwidth-1,ypos,xpos+rwidth-1,ypos+rheight-1); } } /* * set return values */ *x = xpos; *y = ypos; return (ret); } /*------------------------------*/ /* wait_key */ /*------------------------------*/ wait_key () { /* * waits for a key and flushes keyboard buffer. */ if (Batch) { wait_ms (1000); } else { while (!Bconstat (2)) /* wait for a key... */ ; while (Bconstat (2)) /* keep reading while there */ Bconin (2); /* are key inputs... */ } } /*------------------------------*/ /* wait_ms */ /*------------------------------*/ #define MSLOOP 192 /* for function */ wait_ms (ms) int ms; { /* * wait the presribed number of milliseconds. nothing fancy, just * kill time... */ int i; /* * trivial case (no neg wait) */ if (ms <= 0) return; /* * here we do the loop. inner one is just about 1 ms */ for ( ; ms > 0; ms--) for (i = MSLOOP; i > 0; i--) ; return; }