Path: pdxgate!usenet.ee.pdx.edu!reed!ogicse!decwrl!wupost!howland.reston.ans.net!bogus.sura.net!news-feed-1.peachnet.edu!umn.edu!gaia.ucs.orst.edu!ucs.orst.edu!ketrenoj
From: ketrenoj@ucs.orst.edu (Lord Logics)
Newsgroups: comp.sys.ibm.pc.demos
Subject: Scaling code in ASM . . .
Message-ID: <1q568m$hdv@gaia.ucs.orst.edu>
Date: 10 Apr 93 01:01:10 GMT
Organization: University Computing Services - OSU
Lines: 97
NNTP-Posting-Host: ucs.orst.edu
Fellow netters, coders, and other people . . .
Finally a decent news group for exchanging source code . . . here's
my first contribution. I wrote the code in the beginning of last
summer. It was the first code I wrote that implemented the VGA (I had
just purchased VGA) Anyway, this is the fastest method I could come up
with for scaling an image. If there is a faster way, please post, or if
you make any optimizations to this routine, please post them as well.
Sorry if it is hard to follow, and if the comments are confusing.
Oh yeah, I don't know what the normal message limit is, so I'll split
this up into 100 line increments. Should be a total of 3 posts.
NOTE: I haven't tested this routine in quite a while, and I can't
remember if I had made any changes since I last used it. If it doesn't
work, let me know and I'll work on it.
James
-=[ Lord Logics ]=-
ketrenoj@ucs.orst.edu
;----------
.model huge,c
.data
X_SIZE dw 0
Y_SIZE dw 0
X_SKIP dw 0
.code
;*************************************************************************
;** PROC: pixelate()
;** PURP: To put an image onto the screen from VGA memory w/ pitching
;** USAG: pixelate(char *buffer,int x,int y,int ratio);
;** Ratio is a word. The value is in a ratio of 256. So,
;** the ratio of 520 would result in 49% of the original size.
;** (In other words, 256/Ratio = New Size)
;**
;** Buffer is broken down as follows:
;** X Size (2), Y Size (2), then the image.
;**
;** NOTE: No clipping is done for this, and it is currently
;** only written to support chained mode. I am rewriting
;** it to perform clipping and support for unchained video
;** modes. Questions or comments email:
;**
;** ketrenoj@ucs.orst.edu
;** -=[ Lord Logics ]=-
;** Group: None. Want me? Contact me . . .
;**
;*************************************************************************
pixelate proc far
push bp
mov bp,sp
push es
push ds
push si
push di
cld
mov ax,@data
mov ds,ax
mov di,[bp+8] ; Set ES:[DI] to point to the buffer . . .
mov es,di ; :
mov di,[bp+6] ; :
mov dx,es:[di] ; X_SIZE is stored in DX
mov cx,es:[di+2] ; Y_SIZE is stored in CX
mov ax,[bp+14] ; We will now do some adjustemnts via ratio
push dx ; Set up the ratio factor to adjust the
push ax ; : X_SIZE and Y_SIZE, and X and Y POS.
mul dx ; :
mov bx,0100h ; :
div bx ; :
mov X_SIZE,ax ; : Newly adjusted X_SIZE (after pitching)
pop ax ; :
mul cx ; :
div bx ; :
mov Y_SIZE,ax ; : Newly adjusted Y_SIZE (after pitching)
pop dx ; :
;** Now check to make sure that there is indeed something to display . . .
cmp X_SIZE,0 ; Check to see if there is still an image.
jz px_d ; :
cmp Y_SIZE,0 ; :
jz px_d ; :
; Continued in next post . . .
Path: pdxgate!usenet.ee.pdx.edu!reed!ogicse!flop.ENGR.ORST.EDU!gaia.ucs.orst.edu!ucs.orst.edu!ketrenoj
From: ketrenoj@ucs.orst.edu (Lord Logics)
Newsgroups: comp.sys.ibm.pc.demos
Subject: Scaling code in ASM [2/3]
Message-ID: <1q56d9$ho7@gaia.ucs.orst.edu>
Date: 10 Apr 93 01:03:37 GMT
References: <1q568m$hdv@gaia.ucs.orst.edu>
Organization: University Computing Services - OSU
Lines: 87
NNTP-Posting-Host: ucs.orst.edu
; Continued from last post . . .
;** Now we will figure out how much the X and Y POS will be changed . . .
;** On entry:
;** AX - Nothing
;** BX - Nothing
;** CX - Y_SIZE (no pitching)
;** DX - X_SIZE (no pitching)
;** ES:[DI] - Image Buffer
;** DS:[SI] - Nothing
px_sx: sub dx,X_SIZE ; Set up the X_SIZE variance . . .
jge px_xn ; : Variance = 1/2 the size difference . . .
neg dx ; :
shr dx,1 ; :
neg dx ; :
jmp px_sy ; :
px_xn: shr dx,1 ; :
px_sy: sub cx,Y_SIZE ; Set up the Y_SIZE variance . . .
jge px_yn ; :
neg cx ; :
shr cx,1 ; :
neg cx ; :
jmp px_si ; :
px_yn: shr cx,1 ; :
px_si: xor bx,bx ; Clear initial DI displacement.
push dx
mov ax,[bp+12] ; Set up the starting point and check
add ax,cx ; : to make sure that the image will fit
cmp ax,200 ; : within our bounds (ie, the screen).
jge px_d ; :
cmp ax,0 ; :
jge px_s1 ; :
push ax ; :
neg ax ; :
sub Y_SIZE,ax ; : THE FOLLOWING MAY CAUSE
jle px_ddx ; : PROBLEMS DURING CLIPPING.
mov dx,es:[di] ; : Set DX to X_SIZE (no pitching)
push ax ; :
mul dx ; :
mov bx,ax ; : BX stores DI adjustment . . .
mov dx,320 ; :
pop ax ; :
mul dx ; :
mov si,ax ; :
pop ax ; :
jmp px_s2 ; :
;**
;** Exit the procedure . . .
;**
px_ddx: pop dx
px_dax: pop ax
px_d: pop di
pop si
pop ds
pop es
pop bp
ret
px_s1: mov dx,320 ; Adjust SI for proper positioning.
mul dx ; :
mov si,ax ; :
px_s2: pop dx ; Now do the X Adjusting . . .
mov ax,[bp+10] ; Set up the starting point and check
add ax,dx ; : to make sure that the image will fit
cmp ax,320 ; : within our bounds (ie, the screen).
jge px_d ; :
cmp ax,0 ; :
jge px_s3 ; :
neg ax ; :
sub X_SIZE,ax ; :
jle px_d ; :
add bx,ax ; :
jmp px_s4 ; :
px_s3: add si,ax ; Set up screen position adjustment
px_s4: mov cx,bx
mov bx,es:[di]
add di,cx
add di,4
mov cx,Y_SIZE
mov dx,X_SIZE
jmp px_pixel
; Continued in next post . . .
Path: pdxgate!usenet.ee.pdx.edu!reed!ogicse!flop.ENGR.ORST.EDU!gaia.ucs.orst.edu!ucs.orst.edu!ketrenoj
From: ketrenoj@ucs.orst.edu (Lord Logics)
Newsgroups: comp.sys.ibm.pc.demos
Subject: Scaling code in ASM [3/3]
Message-ID: <1q56ii$hrj@gaia.ucs.orst.edu>
Date: 10 Apr 93 01:06:26 GMT
References: <1q568m$hdv@gaia.ucs.orst.edu>
Organization: University Computing Services - OSU
Lines: 87
NNTP-Posting-Host: ucs.orst.edu
; Continued from last post . . .
;**
;** Display the image as quick as possible.
;**
;** On entry:
;** ES:[DI] Points to image buffer
;** DS:[SI] Points to screen memory location (start point)
;** AX - nothing important
;** BX - X_SIZE w/out any pitching. This is used to add to the memory
;** buffer for each line displayed.
;** CX - Y_COUNT size. The number of Y_LINES to display
;** DX - X_COUNT size. The number of X_LINES to display
;**
px_pixel:
;** First we must set up our ratio skipping . . .
push dx ; Save X_COUNT
push bx ; Save X_SIZE
mov bx,[bp+14] ; Set skipping bytes . . .
xor dx,dx ; :
mov ax,0FFFFh ; :
or bx,bx ; :
jz px_pd ; :
div bx ; :
jmp px_pf ; :
px_pd: mov ax,0100h ; :
px_pf: mov [bp+14],ax ; :
pop bx ; Restore X_SIZE
pop dx ; Restore X_COUNT
;** Now we must set up our starting points . . .
mov ax,es ; Set DS:[SI] to our image,
mov ds,ax ; : ES:[DI] to the screen position,
mov ax,0A000h ; : BP to point to the ratio skip,
mov es,ax ; : and AX to the skip, roll over . . .
xchg si,di ; :
add bp,14 ; :
mov al,[bp+1] ; :
xor ah,ah ; :
mov [bp-2],ah ; :
;** Now, actually display the image via to for/next loops . . .
pxq_y: push cx ; Save the Y_COUNT
push ax ; Save the Whole Adjustment
push bx ; Save the X_SIZE (no pitching)
push dx ; Save the X_COUNT
push si ; Save the start of line position
;** Now we will loop through the X_LINE, first setting up the
;** : values needed internally though . . .
mov cx,dx ; Set CX to X_COUNT
mov dl,[bp] ; Set DL to Ratio
xor dh,dh ; Clear the Spill Over
pxq_x: movsb ; Move one byte
dec si ; : Fix the SI from being incremented.
add dh,dl ; Do pitching . . .
adc si,ax ; :
loop pxq_x ; Do the entire X_LINE
;** Now we will adjust for the next X_LINE along the Y_LINE . . .
pop si ; Restore start of line position.
pop bx ; Adjust the dest screen position . . .
add di,320 ; :
sub di,bx ; :
add [bp-2],dl ; Do the pitching . . .
adc ax,0 ; :
mov dx,ax ; :
pop ax ; : Restore AX to the X_SIZE
mov cx,bx ; : Set CX to X_COUNT
mov bx,ax ; : Set BX to X_SIZE
mul dx ; :
add si,ax ; :
pop ax ; : Restore Whole Adjustment
mov dx,cx ; : Set DX to X_COUNT
pop cx ; Restore Y_COUNT
loop pxq_y ; Do the entire Y_LINE.
jmp px_d ; Exit the PIXELATE routine.
pixelate endp ; END OF PIXELATE
end
; That's it. It was written using MASM (don't know what version) but i don't
; think it uses any special pseudo ops from that, so it should work on TASM.
;
Path: pdxgate!usenet.ee.pdx.edu!reed!ogicse!emory!news-feed-1.peachnet.edu!bogus.sura.net!howland.reston.ans.net!ux1.cso.uiuc.edu!news.cso.uiuc.edu!uxa.cso.uiuc.edu!jas37876
From: jas37876@uxa.cso.uiuc.edu (John A. Slagel)
Newsgroups: comp.sys.ibm.pc.demos
Subject: ModeX Bitmap Scaling Code...
Message-ID:
Date: 10 Apr 93 01:43:47 GMT
Sender: usenet@news.cso.uiuc.edu (Net Noise owner)
Organization: University of Illinois at Urbana
Lines: 260
Well, seeing how someone posted code to do scaling, here's my
equivalent code for ModeX. It requires an input bitmap of
128x128 and scales up or down, with clipping, and the clipping
only slows the display down by a constant amount no matter how
much is clipped. This only changes the pixel plane once for
every column, so it is very fast for a ModeX routine.
I'm posting this in hopes that people unselfishly post some
of there own code... Anyway, enjoy.
Oh yeah, erase the .sig at the end.
;=============================================================================
; XSTRETCHBMP By John A. Slagel, jas37876@uxa.cso.uiuc.edu
; Feel free to use this any way you want. Let me know if you find any
; bugs or optimizations, and I would be interested in seeing any final
; projects that use this. Thanks.
;
; This routine stretches (or shrinks) a 128x128 bitmap in VGA ModeX.
; o Color Indices of 255 are "invisible" or "masked" -- They don't draw.
; o Only changes the bitplane 1 time per column, so it is fairly fast.
; o Can only be used in 320x??? modes.
; o Requires a 128x128 bitmap.
; o Will only stretch proportionally.
; o Can stretch from 2 up to very large stretching.
; o Clips according to ClipLt, ClipRt, ClipTp, ClipBt, which should be
; declared in your C routine in another module. You also need to have
; the ModeXseg variable declared elsewhere. Normally A000, A800, etc..
; o Clipping only takes a constant time when it is neccessary.
; o Requires a 386 processor
; o Requires MASM 5.1
; o C-callable as:
; void XSTRETCHBMP( int x, int y, int w, BYTE *Bitmap );
; x,y = Screen Position
; w = Width to stretch it on the screen
; Bitmap = Pointer to 128x128 byte array of pixel data
; Needs extern variables,ClipLt, ClipRt, ClipTp, ClipBt, ModeXseg
;============================================================================
.MODEL LARGE, C
.386
.DATA
SC_INDEX1 EQU 03C4h
SC_INDEX2 EQU 03C5h
MAP_MASK EQU 2
INVISIBLE_COLOR EQU 255
extrn ClipTp:word
extrn ClipLt:word
extrn ClipRt:word
extrn ClipBt:word
extrn ModeXseg:word
.CODE
XSTRETCHBMP PROC FAR USES DI SI, DestXStart:WORD, DestYStart:WORD, DestSize:WORD, Bitmap:FAR PTR
LOCAL DestHeight:WORD, DecisionY:WORD, DestWidth:WORD, DecisionX:WORD, DestSize2:WORD, Doff:WORD, Soff:WORD
mov DestHeight,0
mov DecisionY, 0
mov DestWidth, 0
mov DecisionX, 0
mov DestSize2, 0
mov Doff, 0
mov Soff, 0
cmp DestSize, 2
jl Done ; If it is too small then exit
mov ax, DestYStart
cmp ax, ClipBt
jg Done ; If it is too far down then exit
add ax, DestSize
dec ax
cmp ax, ClipTp
jl Done ; If it is too far up then exit
mov ax, DestXStart
cmp ax, ClipRt
jg Done ; If it is too far right then exit
add ax, DestSize
dec ax
cmp ax, ClipLt
jl Done ; If it is too far left then exit
mov ax, DestSize
mov DestWidth, ax ; Initialize DestWidth=DestSize
mov DestHeight, ax ; Initialize DestHeight=DestSize
mov Soff, 0 ; Point Soff to start of bitmap
mov DestSize2, ax
shl DestSize2, 1 ; Calculate DestSize*2 for later
shl ax, 1
neg ax
mov DecisionX, ax ; DecisionX = -DestSize
mov DecisionY, ax ; DecisionY = -DestSize
movsx eax, ClipTp
movsx ecx, DestYStart
sub eax, ecx ; EAX = ClipTp-DestYStart
jle NoTopClip
;Clip off the top
sub DestHeight, ax ; DestHeight -= (ClipTp-DestYStart)
mov ebx, eax ; EBX = AmountClippedY
xor edx, edx ; EDX = 0
shl eax, 7 ; EDX:EAX = AmountClippedY * 128
movzx ecx, DestSize
div ecx ; EAX (SourceStartY) = EDX:EAX / DestSize
add Soff, ax ; Soff = SourceStartY (EAX)
shl Soff, 7 ; * 128
shl ebx, 8 ; EBX = AmountClippedY * 256
shl ecx, 1 ; ECX = DestSize2
mul ecx ; EDX:EAX = SourceStartY * DestSize2
sub ebx, eax
add DecisionY, bx
mov ax, ClipTp
mov DestYStart, ax
NoTopClip:
mov ax, DestYStart
add ax, DestHeight
dec ax
cmp ax, ClipBt
jle NoBottomClip
; Clip off the bottom
mov ax, ClipBt
sub ax, DestYStart
inc ax
mov DestHeight, ax
NoBottomClip:
movsx eax, ClipLt
movsx ecx, DestXStart
sub eax, ecx
jle NoLeftClip
;Clip off the left side
sub DestWidth, ax ; DestWidth -= (ClipLT-DestXStart)
mov ebx, eax ; EBX = AmountClippedX
xor edx, edx ; EDX = 0
shl eax, 7 ; EDX:EAX = AmountClippedX * 128
movzx ecx, DestSize
div ecx ; EAX (SourceStartX) = EDX:EAX / DestSize
add Soff, ax ; Soff += SourceStartX (EAX)
shl ebx, 8 ; EBX = AmountClippedX * 256
shl ecx, 1 ; ECX = DestSize2
mul ecx ; EDX:EAX = SourceStartX * DestSize2
sub ebx, eax
add DecisionX, bx
mov ax, ClipLt
mov DestXStart, ax
NoLeftClip:
mov ax, DestXStart
add ax, DestWidth
dec ax
cmp ax, ClipRt
jle NoClipRight
; Clip off the right
mov ax, ClipRt
sub ax, DestXStart
inc ax
mov DestWidth, ax
;Calculate starting video address
NoClipRight:
mov ax, ModeXseg
mov gs, ax
movsx eax, DestYStart
lea eax, [eax*2]
lea eax, [eax*8]
lea eax, [eax+eax*4]
mov bx, DestXStart
mov cx, bx
shr bx, 2
add ax, bx
mov Doff, ax ; gS:Doff -> VGA memory
mov dx, SC_INDEX1
mov al, MAP_MASK
out dx, al
inc dx
and cx, 3
mov al, 11h
shl al, cl
out dx, al ; Select the first plane
lfs si, Bitmap
add Soff, si
mov dx, DestSize2
ColumnLoop:
mov di, Doff
mov si, Soff
mov bx, DecisionY
mov cx, DestHeight
inc cx
jmp NextPixel
RowLoop:
mov gs:[di], ah
add di, 80
add bx, 256
js Visible
IncSourceY:
add si, 128
sub bx, dx
jns IncSourceY
NextPixel:
mov ah, fs:[si]
cmp ah, INVISIBLE_COLOR
je MaskedPixel
Visible:
loop RowLoop
DoneWithCol:
rol al, 1
adc Doff, 0
mov dx, SC_INDEX2
out dx, al
mov dx, DestSize2
add DecisionX, 256
js NextCol
mov bx, DecisionX
IncSourceX:
inc Soff
sub bx, dx
jns IncSourceX
mov DecisionX, bx
NextCol:
dec DestWidth
jnz ColumnLoop
Done:
ret
MRowLoop:
add di, 80
add bx, 256
js MaskedPixel
MSourceIncY:
add si, 128
sub bx, dx
jns MSourceIncY
mov ah, fs:[si]
cmp ah, INVISIBLE_COLOR
jne Visible
MaskedPixel:
loop MRowLoop
jmp DoneWithCol
XSTRETCHBMP ENDP
END
--
-----------------------------------------------------------------------------
John A. Slagel "My old man used to tell me, before he left this
j-slagel1@uiuc.edu shitty world, never chase buses or women- you
(217) 337-7930 always get left behind." -The Marlboro Man