[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]
unit fastputimage;
{
*******************************************************
* *VERY* FAST PUTIMAGE *
*******************************************************
* (C) Petr Sulla 1996 *
* E-mail: xsulla@fi.muni.cz *
*******************************************************
* Public domain, use at your own risk. Enjoy it !!! *
*******************************************************
Hi all ! I was just in need of a *REALLY* fast putimage but I couldn't
find it anywhere. So I sat down for a couple of hours and here it is !
The FASTEST putimage I've ever seen.
The x-position must be a multiplicate of 8 due to the VGA/EGA
memory organisation. (will be automatically rounded)
The image should not exceed the screen size (this case is not tested
and could cause strange results...
The image structure is *not* compatible with the Borland's one.
Old images can be easily converted by displaying them and then
saving them using this new getimage.
It could be possibly even faster - some code optimization could help.
I find it fast enough as it is now, anyway ;-)
An example follows.
}
interface
{$g+}
function myimagesize(x,y,x0,y0:word):word;
procedure mygetimage(x,y,x0,y0:word;p:pointer);
procedure myputimage(x,y:word;p:pointer);
procedure waitretrace;
implementation
function myimagesize(x,y,x0,y0:word):word;
var dummy:longint;
sx,sy:word;
begin
sx:=succ(abs(x0-x) div 8);
sy:=succ(abs(y0-y));
dummy:=sx*sy*4+10; {*4 because of 4 bitplanes}
if dummy<65520 then
myimagesize:=dummy
else
myimagesize:=0;
end;
procedure mygetimage(x,y,x0,y0:word;p:pointer);assembler;
var m:word;
asm
sti
push es
push ds
cld {rep adds}
les di,[p] {x0 <- width, y0 <- height, write to buffer}
mov ax,x0
sub ax,x
shr ax,3 {x0:=x0 div 8}
mov x0,ax
mov es:[di],ax
inc x0
mov ax,y0
sub ax,y
mov y0,ax
mov es:[di+2],ax
inc y0
add di,4 {es:di <- pointer to data}
shr x,3 {x:=x div 8}
mov bx,y {m:=y*80+x - offset in vram}
mov cx,bx
shl bx,4
shl cx,6
add bx,cx
add bx,x
mov m,bx
mov ax,0a000h {ds:si <- beginning of vram}
mov ds,ax
mov bx,y0 {bx - lines counter}
mov dx,03ceh {dx - port address}
mov al,4
out dx,al
inc dx
@@1:
mov ah,4 {ah - 3=1.bit plane, 2=2.bitpl.,1=3.bitpl.,0=4.bitpl.}
@@2:
mov al,ah
dec al
out dx,al {send number of bitplane to the graphic card}
mov si,m {offset in videoram}
mov cx,x0 {image width to counter}
rep movsb {send cx bytes from DS:SI(vram) to ES:DI(image)}
dec ah {decrement al - next bitplane}
jnz @@2 {is zero ? - no=next bitplane}
add m,80 {next line in vram}
dec bx {decrement lines counter}
jnz @@1 {last line ? no=next line}
dec dx {set graphic card back to std. modus}
mov al,3
out dx,al
inc dx
xor al,al
out dx,al
pop ds
pop es
cli
end;
procedure myputimage(x,y:word;p:pointer);assembler;
var sx,sy,m:word;
asm
sti
push es
push ds
cld {rep adds}
shr x,3 {x:=x div 8}
mov bx,y {m:=y*80+x - offset in vram}
mov cx,bx
shl bx,4
shl cx,6
add bx,cx
add bx,x
mov m,bx
lds si,[p] {sx <- width, sy <- height}
mov ax,word ptr ds:[si]
inc ax
mov sx,ax
mov ax,word ptr ds:[si+2]
inc ax
mov sy,ax
add si,4 {ds:si <- pointer to data}
mov ax,0a000h {es:di <- beginning of vram}
mov es,ax
mov bx,sy {bx - lines counter}
mov dx,03c4h {dx - port address}
mov al,2
out dx,al
inc dx
@@1:
mov al,8 {al - 8=1.bit plane, 4=2.bitpl.,2=3.bpl.,1=4.bpl.}
@@2:
out dx,al {send bitplane number to the graphic card}
mov di,m {offset in videoram}
mov cx,sx {image width to counter}
rep movsb {send cx bytes from DS:SI(image) to ES:DI(vram)}
shr al,1 {divide al by 2 - next bitplane of 4}
jnz @@2 {is zero ? - no=next bitplane}
add m,80 {next line in vram}
dec bx {decrement lines counter}
jnz @@1 {last line ? no=next line}
dec dx {set graphic card back to std. modus}
mov al,2
out dx,al
inc dx
mov al,15
out dx,al
pop ds
pop es
cli
end;
procedure waitretrace;assembler; {can be handy for smooth animation}
asm
mov dx,$3da
@1: in al,dx
test al,8
jz @1
@2: in al,dx
test al,8
jnz @2
end;
end.
{------------- 8< ------ Cut here ---------- 8< ----------------------}
{
*******************************************************
* FAST PUTIMAGE EXAMPLE *
*******************************************************
* (C) Petr Sulla 1996 *
* E-mail: xsulla@fi.muni.cz *
*******************************************************
* Public domain, use at your own risk. Enjoy !!! *
*******************************************************
}
uses crt,graph,fastputimage;
var gd,gm:integer;
p,q:pointer;
procedure garbage;
var i,j,k:integer;
begin
for i:=1 to 80 do
begin
j:=random(15)+1;
setcolor(j);
setfillstyle(1,j);
j:=random(200);
k:=random(200);
case random(3) of
0:rectangle(j,k,j+random(200),k+random(200));
1:bar(j,k,j+random(200),k+random(200));
2:circle(j,k,random(200));
end;
end;
end;
begin
gd:=detect;
initgraph(gd,gm,''); {<- insert path to your egavga.bgi here}
getmem(p,myimagesize(0,0,300,343)); {get some memory for the two test images}
getmem(q,myimagesize(0,0,300,343));
randomize;
setfillstyle(1,8);
bar(0,0,getmaxx,getmaxy);
garbage; {generate some garbage on screen}
mygetimage(0,0,300,343,p); {and make it to an image ;-) }
repeat until keypressed;
while keypressed do readkey;
cleardevice;
setfillstyle(1,13); {and the same once more with}
bar(0,0,getmaxx,getmaxy); {another background color}
garbage;
mygetimage(0,0,300,343,q);
repeat until keypressed;
while keypressed do readkey;
cleardevice;
repeat
myputimage(random(330),random(135),p); {display both images in a loop}
myputimage(random(330),random(135),q);
until keypressed;
while keypressed do readkey;
freemem(p,myimagesize(0,0,300,343)); {free the memory occupied by the images}
freemem(q,myimagesize(0,0,300,343));
closegraph;
end.
[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]