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