home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1989 / 06 / pixfil.asc < prev    next >
Text File  |  1989-05-27  |  9KB  |  301 lines

  1. _GRAPHICS PROGRAMMING_
  2. by Kent Porter
  3.  
  4. [LISTING ONE]
  5.  
  6. ; EGAPIXEL.ASM: Reads EGA pixel value directly from video memory
  7. ; Returns pixel value at x, y, or -1 if outside viewport
  8. ; Microsoft MASM 5.1
  9. ; C prototype is 
  10. ;      int far egapixel (int x, int y);
  11. ; To be included in GRAFIX.LIB
  12. ; K. Porter, DDJ ``Graphics Programming'' column, June '89
  13.  
  14. .MODEL  LARGE
  15.         PUBLIC  _egapixel
  16.         EXTRN   _vuport : WORD          ; far ptr to vuport structure
  17.  
  18. ; Arguments passed from C
  19. x       EQU     [bp+6]                  ; Arguments passed from C
  20. y       EQU     [bp+8]
  21.  
  22. ; Macro to build pixel value in BL
  23. pixval  MACRO
  24.         out     dx, ax                  ; set 6845 for bit plane
  25.         mov     bh, BYTE PTR es:[si]    ; get byte from current bit plane
  26.         and     bh, ch                  ; mask bit
  27.         neg     bh                      ;  and flip it
  28.         rol     bx, 1                   ; move to bit 0 in accum (BH)
  29.         dec     ah                      ; next bit plane
  30.         ENDM
  31.  
  32. .CODE
  33. _egapixel       PROC FAR
  34.         push    bp                      ; Entry processing
  35.         mov     bp, sp
  36.         push    si                      ; Save SI (used here)
  37.  
  38. ; Point ES:[BX] to vuport structure
  39.         mov     ax, _vuport+2           ; get pointer segment
  40.         mov     es, ax
  41.         mov     bx, _vuport             ; get offset
  42.  
  43. ; Quit if coordinates outside viewport
  44.         mov     al, -1                  ; return value if outside
  45.         mov     cx, y                   ; get y
  46.         cmp     cx, WORD PTR es:[bx+6]  ; is y within viewport?
  47.         jge     exit                    ; quit if not
  48.         mov     dx, x                   ; get x
  49.         cmp     dx, WORD PTR es:[bx+4]  ; is x within viewport?
  50.         jge     exit                    ; quit if not
  51.  
  52. ; Map pixel coordinates to current viewport
  53.         add     dx, WORD PTR es:[bx]    ; offset x by vuport.left
  54.         push    dx                      ; save remapped X (used later)
  55.         add     cx, WORD PTR es:[bx+2]  ; offset y by vuport.top
  56.  
  57. ; Point ES to video memory segment        
  58.         mov     bx, 0A000h
  59.         mov     es, bx
  60.  
  61. ; Row offset = y * 80;
  62.         push    dx                      ; (modified by MUL)
  63.         mov     ax, cx                  ; get y
  64.         mov     bx, 80
  65.         mul     bx                      ; y * 80
  66.         mov     bx, ax                  ; into BX
  67.  
  68. ; Column offset = x SHR 3
  69.         pop     ax                      ; get x back
  70.         mov     cl, 3                   ; shift operand
  71.         shr     ax, cl                  ; column offset
  72.  
  73. ; Complete address of pixel byte
  74.         add     bx, ax                  ; BX = row offset + col offset
  75.         mov     si, bx                  ; ES:SI = address
  76.  
  77. ; Build bit mask for pixel 
  78.         pop     cx                      ; get x back
  79.         and     cl, 7                   ; isolate low-order bits
  80.         xor     cl, 7                   ; number of bits to shift
  81.         mov     ch, 1                   ; start bit mask
  82.         shl     ch, cl                  ; shift for pixel
  83.         xor     bl, bl                  ; accumulator for pixel value
  84.  
  85. ; Set graphics controller Read Map Select Register
  86.         mov     dx, 03CEh               ; 6845 command register
  87.         mov     ax, 0304h               ; first bit plane = 3
  88.  
  89. ; Read bit planes 3-0, accumulating bits in BL
  90.         pixval
  91.         pixval
  92.         pixval
  93.         pixval
  94.         
  95. ; AX = return value for function
  96.         mov     al, bl
  97.                 
  98. ; Send pixel value back in AL
  99. exit:   xor     ah, ah
  100.         pop     si
  101.         mov     sp, bp
  102.         pop     bp
  103.         retf
  104. _egapixel       ENDP
  105.                 END
  106.  
  107.  
  108. [LISTING TWO]
  109.  
  110.  
  111. /* RICOCHET.C: A line moving diagonally "feels" its way among obstacles */
  112. /* Illustrates pixel-reading with egapixel() */
  113. /* K. Porter, DDJ ``Graphics Programming'' column, June '89 */
  114.  
  115. #include "grafix.h"
  116. #include <conio.h>
  117.  
  118. void main ()
  119. {
  120. int  x = 638;         /* current X position of line */
  121. int  y = 348;         /* and its Y */
  122. int  xdir = -1;       /* current X direction (-1 = left, 1 = right) */
  123. int  ydir = -1;       /* and Y direction (-1 = up, 1 = down */
  124.  
  125.   if (init_video (EGA)) {
  126.  
  127.     /* Draw a maze and border */
  128.     set_color1 (15);
  129.     draw_rect (0, 0, 639, 349);
  130.     draw_line (141, 40, 141, 119);
  131.     hline (141, 119, 120);
  132.     draw_line (421, 0, 421, 100);
  133.     hline (540, 199, 80);
  134.     hline (360, 160, 120);
  135.     hline (300, 261, 120);
  136.     draw_line (200, 259, 200, 330);
  137.     draw_line (99, 240, 99, 349);
  138.  
  139.     /* Send the line bouncing around */
  140.     set_color1 (4);
  141.     while (!kbhit()) {
  142.       if (egapixel (x+xdir, y) == 15)     /* feel ahead horizontally */
  143.         xdir = -xdir;                         /* reverse if obstacle */
  144.       if (egapixel (x, y+ydir) == 15)             /* same vertically */
  145.         ydir = -ydir;
  146.       x += xdir;                                 /* advance position */
  147.       y += ydir;
  148.       draw_point (x, y);
  149.     }
  150.     getch();                                /* clear keyboard buffer */
  151.   }
  152. }        
  153.  
  154.  
  155. [LISTING THREE]
  156.  
  157.  
  158. /* FILL.C: Line adjacency flood fill algorithm */
  159. /* For inclusion in GRAFIX.LIB */
  160. /* K. Porter, DDJ ``Graphics Programming'' column, June '89 */
  161. /* ---------------------------------------------------- */
  162.  
  163. #include "grafix.h"
  164.  
  165. extern int color1;                          /* from GRAFIX library */
  166.  
  167. int far floodfill (int  sx, int sy,         /* seed coords */
  168.                    int  border,             /* border color */
  169.                    int  dir,                /* direction (-1=up, 1=down) */
  170.                    int  pleft, int prite)   /* ends of previous line */
  171. {
  172. int  x;                  /* current column */
  173. int  left, rite;         /* ends of current line */
  174. byte pixel;              /* detected pixel value */
  175. extern byte far isborder (int, int, byte);
  176. int near leftborder (int, int, byte),
  177.     near rightborder (int, int, byte);
  178.  
  179.   /* fix caller's arguments */
  180.   if (dir == 0) dir = -1;
  181.   else
  182.     if (dir > 0) dir = 1;
  183.  
  184.   /* find ends of seed row */
  185.   left = leftborder  (sx, sy, border);
  186.   rite = rightborder (sx, sy, border);
  187.  
  188.   /* fill seed row */
  189.   if (left < rite)
  190.     draw_line (left+1, sy, rite-1, sy);
  191.   else
  192.     return rite;
  193.  
  194.   /* fill adjacent rows in same direction */
  195.   for (x = left+1; x < rite; x++) {
  196.     pixel = egapixel (x, sy+dir);      /* inspect adjacent row */
  197.     if ((pixel != color1) && (pixel != border))
  198.       x = floodfill (x, sy+dir, border, dir, left, rite);
  199.   }
  200.  
  201.   /* fill adjacent rows in opposite direction */
  202.   for (x = left+1; x < pleft; x++) {
  203.     pixel = egapixel (x, sy-dir);
  204.     if ((pixel != color1) && (pixel != border))
  205.       x = floodfill (x, sy-dir, border, -dir, left, rite);
  206.   }
  207.  
  208.   for (x = prite+1; x < rite; x++) {
  209.     pixel = egapixel (x, sy-dir);
  210.     if ((pixel != color1) && (pixel != border))
  211.       x = floodfill (x, sy-dir, border, -dir, left, rite);
  212.   }
  213.   return rite;
  214. } /* -------------------------------------------------------------- */
  215. /* Following are local routines serving floodfill() */
  216.  
  217. int near leftborder (int x, int y, byte border)
  218. {
  219. byte pixel;
  220.  
  221.   do {
  222.     --x;
  223.     pixel = egapixel (x, y);
  224.     if ((pixel == border) || (pixel == color1))
  225.       break;
  226.   } while (x > 0);
  227.   return x;
  228. } /* -------------------------------------------------------------- */
  229.  
  230. int near rightborder (int x, int y, byte border)
  231. {
  232. byte pixel;
  233.  
  234.   do {
  235.     ++x;
  236.     pixel = egapixel (x, y);
  237.     if ((pixel == border) || (pixel == color1))
  238.       break;
  239.   } while (x < vp_width());
  240.   return x;
  241. } /* -------------------------------------------------------------- */
  242.  
  243.  
  244. [LISTING FOUR]
  245.  
  246.  
  247. /* From June, '89 */
  248. /* -------------- */
  249. int far egapixel (int x, int y);         /* get pixel value at x, y */
  250.  
  251. int far floodfill (int  sx, int sy,        /* seed coords */
  252.                    int  border,            /* border color */
  253.                    int  dir,               /* pass as 0 */
  254.                    int  pleft, int prite); /* make same as sx */
  255.  
  256. [LISTING FIVE]
  257.  
  258.  
  259. /* FILLS.C: Various filled figures */
  260. /* K. Porter, DDJ ``Graphics Programming'' column, June '89 */
  261.  
  262. #include "grafix.h"
  263. #include <conio.h>
  264.  
  265. int triangle[] = {
  266.   20,300, 120,300, 70,200, 20,300
  267. };
  268. int star[] = {
  269.   60,10,  120,80,  20,60,  100,140,  140,110, 
  270.   260,190,  220,70,  370,30,  180,40,  60,10
  271. };
  272. int house[] = {
  273.   400,200, 400,340, 600,340, 600,200, 
  274.   500,100, 400,200
  275. };
  276.  
  277. void main() {
  278. int x, y;
  279.  
  280.   if (init_video (EGA)) {
  281.     set_color1 (15);
  282.     polyline (3, triangle);
  283.     set_color1 (4);
  284.     floodfill (70, 250, 15, 0, 60, 60);
  285.  
  286.     set_color1 (14);
  287.     polyline (9, star);
  288.     set_color1 (6);
  289.     floodfill (140, 80, 14, 0, 140, 140);
  290.  
  291.     set_color1 (15);
  292.     polyline (5, house);
  293.     for (x = 430; x < 560; x += 60)
  294.       for (y = 220; y < 300; y += 60)
  295.         draw_rect (x, y, 20, 35);
  296.     set_color1 (7);
  297.     floodfill (500, 200, 15, 0, 500, 500);
  298.     getch();  
  299.   }
  300. }
  301.