home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddj8906.arc
/
PIXFIL.ASC
< prev
next >
Wrap
Text File
|
1989-05-27
|
9KB
|
301 lines
_GRAPHICS PROGRAMMING_
by Kent Porter
[LISTING ONE]
; EGAPIXEL.ASM: Reads EGA pixel value directly from video memory
; Returns pixel value at x, y, or -1 if outside viewport
; Microsoft MASM 5.1
; C prototype is
; int far egapixel (int x, int y);
; To be included in GRAFIX.LIB
; K. Porter, DDJ ``Graphics Programming'' column, June '89
.MODEL LARGE
PUBLIC _egapixel
EXTRN _vuport : WORD ; far ptr to vuport structure
; Arguments passed from C
x EQU [bp+6] ; Arguments passed from C
y EQU [bp+8]
; Macro to build pixel value in BL
pixval MACRO
out dx, ax ; set 6845 for bit plane
mov bh, BYTE PTR es:[si] ; get byte from current bit plane
and bh, ch ; mask bit
neg bh ; and flip it
rol bx, 1 ; move to bit 0 in accum (BH)
dec ah ; next bit plane
ENDM
.CODE
_egapixel PROC FAR
push bp ; Entry processing
mov bp, sp
push si ; Save SI (used here)
; Point ES:[BX] to vuport structure
mov ax, _vuport+2 ; get pointer segment
mov es, ax
mov bx, _vuport ; get offset
; Quit if coordinates outside viewport
mov al, -1 ; return value if outside
mov cx, y ; get y
cmp cx, WORD PTR es:[bx+6] ; is y within viewport?
jge exit ; quit if not
mov dx, x ; get x
cmp dx, WORD PTR es:[bx+4] ; is x within viewport?
jge exit ; quit if not
; Map pixel coordinates to current viewport
add dx, WORD PTR es:[bx] ; offset x by vuport.left
push dx ; save remapped X (used later)
add cx, WORD PTR es:[bx+2] ; offset y by vuport.top
; Point ES to video memory segment
mov bx, 0A000h
mov es, bx
; Row offset = y * 80;
push dx ; (modified by MUL)
mov ax, cx ; get y
mov bx, 80
mul bx ; y * 80
mov bx, ax ; into BX
; Column offset = x SHR 3
pop ax ; get x back
mov cl, 3 ; shift operand
shr ax, cl ; column offset
; Complete address of pixel byte
add bx, ax ; BX = row offset + col offset
mov si, bx ; ES:SI = address
; Build bit mask for pixel
pop cx ; get x back
and cl, 7 ; isolate low-order bits
xor cl, 7 ; number of bits to shift
mov ch, 1 ; start bit mask
shl ch, cl ; shift for pixel
xor bl, bl ; accumulator for pixel value
; Set graphics controller Read Map Select Register
mov dx, 03CEh ; 6845 command register
mov ax, 0304h ; first bit plane = 3
; Read bit planes 3-0, accumulating bits in BL
pixval
pixval
pixval
pixval
; AX = return value for function
mov al, bl
; Send pixel value back in AL
exit: xor ah, ah
pop si
mov sp, bp
pop bp
retf
_egapixel ENDP
END
[LISTING TWO]
/* RICOCHET.C: A line moving diagonally "feels" its way among obstacles */
/* Illustrates pixel-reading with egapixel() */
/* K. Porter, DDJ ``Graphics Programming'' column, June '89 */
#include "grafix.h"
#include <conio.h>
void main ()
{
int x = 638; /* current X position of line */
int y = 348; /* and its Y */
int xdir = -1; /* current X direction (-1 = left, 1 = right) */
int ydir = -1; /* and Y direction (-1 = up, 1 = down */
if (init_video (EGA)) {
/* Draw a maze and border */
set_color1 (15);
draw_rect (0, 0, 639, 349);
draw_line (141, 40, 141, 119);
hline (141, 119, 120);
draw_line (421, 0, 421, 100);
hline (540, 199, 80);
hline (360, 160, 120);
hline (300, 261, 120);
draw_line (200, 259, 200, 330);
draw_line (99, 240, 99, 349);
/* Send the line bouncing around */
set_color1 (4);
while (!kbhit()) {
if (egapixel (x+xdir, y) == 15) /* feel ahead horizontally */
xdir = -xdir; /* reverse if obstacle */
if (egapixel (x, y+ydir) == 15) /* same vertically */
ydir = -ydir;
x += xdir; /* advance position */
y += ydir;
draw_point (x, y);
}
getch(); /* clear keyboard buffer */
}
}
[LISTING THREE]
/* FILL.C: Line adjacency flood fill algorithm */
/* For inclusion in GRAFIX.LIB */
/* K. Porter, DDJ ``Graphics Programming'' column, June '89 */
/* ---------------------------------------------------- */
#include "grafix.h"
extern int color1; /* from GRAFIX library */
int far floodfill (int sx, int sy, /* seed coords */
int border, /* border color */
int dir, /* direction (-1=up, 1=down) */
int pleft, int prite) /* ends of previous line */
{
int x; /* current column */
int left, rite; /* ends of current line */
byte pixel; /* detected pixel value */
extern byte far isborder (int, int, byte);
int near leftborder (int, int, byte),
near rightborder (int, int, byte);
/* fix caller's arguments */
if (dir == 0) dir = -1;
else
if (dir > 0) dir = 1;
/* find ends of seed row */
left = leftborder (sx, sy, border);
rite = rightborder (sx, sy, border);
/* fill seed row */
if (left < rite)
draw_line (left+1, sy, rite-1, sy);
else
return rite;
/* fill adjacent rows in same direction */
for (x = left+1; x < rite; x++) {
pixel = egapixel (x, sy+dir); /* inspect adjacent row */
if ((pixel != color1) && (pixel != border))
x = floodfill (x, sy+dir, border, dir, left, rite);
}
/* fill adjacent rows in opposite direction */
for (x = left+1; x < pleft; x++) {
pixel = egapixel (x, sy-dir);
if ((pixel != color1) && (pixel != border))
x = floodfill (x, sy-dir, border, -dir, left, rite);
}
for (x = prite+1; x < rite; x++) {
pixel = egapixel (x, sy-dir);
if ((pixel != color1) && (pixel != border))
x = floodfill (x, sy-dir, border, -dir, left, rite);
}
return rite;
} /* -------------------------------------------------------------- */
/* Following are local routines serving floodfill() */
int near leftborder (int x, int y, byte border)
{
byte pixel;
do {
--x;
pixel = egapixel (x, y);
if ((pixel == border) || (pixel == color1))
break;
} while (x > 0);
return x;
} /* -------------------------------------------------------------- */
int near rightborder (int x, int y, byte border)
{
byte pixel;
do {
++x;
pixel = egapixel (x, y);
if ((pixel == border) || (pixel == color1))
break;
} while (x < vp_width());
return x;
} /* -------------------------------------------------------------- */
[LISTING FOUR]
/* From June, '89 */
/* -------------- */
int far egapixel (int x, int y); /* get pixel value at x, y */
int far floodfill (int sx, int sy, /* seed coords */
int border, /* border color */
int dir, /* pass as 0 */
int pleft, int prite); /* make same as sx */
[LISTING FIVE]
/* FILLS.C: Various filled figures */
/* K. Porter, DDJ ``Graphics Programming'' column, June '89 */
#include "grafix.h"
#include <conio.h>
int triangle[] = {
20,300, 120,300, 70,200, 20,300
};
int star[] = {
60,10, 120,80, 20,60, 100,140, 140,110,
260,190, 220,70, 370,30, 180,40, 60,10
};
int house[] = {
400,200, 400,340, 600,340, 600,200,
500,100, 400,200
};
void main() {
int x, y;
if (init_video (EGA)) {
set_color1 (15);
polyline (3, triangle);
set_color1 (4);
floodfill (70, 250, 15, 0, 60, 60);
set_color1 (14);
polyline (9, star);
set_color1 (6);
floodfill (140, 80, 14, 0, 140, 140);
set_color1 (15);
polyline (5, house);
for (x = 430; x < 560; x += 60)
for (y = 220; y < 300; y += 60)
draw_rect (x, y, 20, 35);
set_color1 (7);
floodfill (500, 200, 15, 0, 500, 500);
getch();
}
}