PAGE ,132 TITLE BltProp.asm NAME BltProp ?WIN = 0 ?PLM = 1 .286 .xlist include cmacros.inc include windows.inc .list ; The following structure should be used to access high and low ; words of a DWORD. This means that "word ptr foo[2]" -> "foo.hi". LONG struc lo dw ? hi dw ? LONG ends FARPOINTER struc off dw ? sel dw ? FARPOINTER ends MAXWIDTH = 1500 externA __AHINCR sBegin DATA ;;externW sColorsOut ;;externW GrayThresh ;;externW LoThresh ;;externW HiThresh ;;externW Prop ;;externW Mult GrayThresh dw 128 ; 135 LoThresh dw 128 ; 120 HiThresh dw 192 ; 200 Prop dw 8 ; 6 Mult dw 32, 32, 32 ; 28, 28, 28 usPalMult DW 3 * 256 DUP (?) sCol DW 0 v DW 3 DUP (?) val DW 3 DUP (?) errx DW 3 DUP (?) errz DW 3 DUP (?) erry DW 3 * MAXWIDTH DUP (?) ; the output Color Table ; ; The pixel values that index this table are generated by PropImage ; as follows: ; ; bits 7x543210 ; | |||||| ; | |||||+-- set iff RED > HiThresh ; | ||||+--- set iff RED > LoThresh ; | |||+---- set iff GREEN > HiThresh ; | ||+----- set iff GREEN > LoThresh ; | |+------ set iff BLUE > HiThresh ; | +------- set iff BLUE > LoThresh ; +--------- set iff all colors > GrayThresh ; ; The color values map to the appropriate 16 colors of the standard ; palette. ; ; 0 - LoThresh 0 ; LoThresh - HiThresh 128 ; HiThresh - 255 255 ; ; As usual the magic grays are special cased ; dwrgb macro n red = 0 green = 0 blue = 0 if n and 010101b rgbval = 0FFh else rgbval = 080h endif if n and 000011b red = rgbval endif if n and 001100b green = rgbval endif if n and 110000b blue = rgbval endif if n eq 0AAh red = 0C0h green = 0C0h blue = 0C0h endif if n eq 080h red = 080h green = 080h blue = 080h endif dw red,green,blue endm sColorsOut label word n = 0 rept 256 dwrgb n n = n + 1 endm sEnd DATA sBegin CODE assumes ds,DATA assumes ss,DATA assumes cs,CODE ;-------------------------------------------------------------------------; ; ; BltProp ; ; Does error proagation on a input 8 bpp DIB producing a 8 bpp DIB ; that only uses 16 colors. ; ; assumes SS == DS !! ; ; Entry: ; ; Returns: ; AX = 1 ; Error Returns: ; AX = 0 if error ; Registers Preserved: ; SI,DI,DS,BP ; Registers Destroyed: ; AX,BX,CX,DX,FLAGS ; Calls: ; ;-------------------------------------------------------------------------; cProc BltProp, , parmD pbiSrc ; BITMAP info for source DIB parmD pbSrc ; Source bits pointer parmW SrcX ; Source X offset parmW SrcY ; Source Y offset parmW SrcXE ; Source X extent parmW SrcYE ; Source Y extent parmD pbiDst ; BITMAP info for destination DIB parmD pbDst ; Destination bits pointer parmW DstX ; Destination X offset parmW DstY ; Destination Y offset localW cbScanSrc ; width of a source scanline localW cbScanDst localW cbIncS ; next scan localW cbIncD cBegin mov ax,ds mov es,ax lea di,erry ; clear out erry[] xor ax,ax mov cx,3 * MAXWIDTH rep stosb ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; pre-multiply the input palette by the intensity multipliers ; ; for (row = 0; row < cColorsIn; ++row) ; for (clr = 0; clr < 3; ++clr) ; usPalMult[row][2-clr] = rcbmIn.argbColor[row][clr] * Mult[2-clr] / 32; ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; les di,pbiSrc ; es:[di] --> source BITMAPINFO mov ax,word ptr es:[di].biWidth ; DWORD align bitmap width add ax,3 and ax,not 3 mov cbScanSrc,ax add di,word ptr es:[di].biSize ; es:[di] --> color table lea si,usPalMult ; ds:[si] --> usPalMult mov cx,256 PalMulLoop: xor bx,bx irp rgbX, xor ah,ah mov al,es:[di].&rgbX mul Mult[bx] shr ax,5 mov ds:[si+bx],ax add bx,2 endm add si,6 add di,4 loop PalMulLoop ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; fill in the destination color table ; ; for (inx = 0; inx < 256; ++inx) ; for (clr = 0; clr < 3; ++clr) ; rcbmOut.argbColor[inx][clr] = (BYTE)sColorsOut[inx][2-clr]; ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; les di,pbiDst ; es:[di] --> destination BITMAPINFO mov ax,word ptr es:[di].biWidth ; DWORD align bitmap width add ax,3 and ax,not 3 mov cbScanDst,ax add di,word ptr es:[di].biSize ; es:[di] --> color table lea si,sColorsOut ; ds:[si] --> sColorsOut mov cx,256 sColorsOutLoop: lodsw mov es:[di].rgbRed ,al lodsw mov es:[di].rgbGreen,al lodsw mov es:[di].rgbBlue ,al add di,4 loop sColorsOutLoop ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; caclulate amount to add to source/dest pointer to get the the next scanline ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; mov bx,SrcXE mov ax,cbScanSrc sub ax,bx ; cbIncS = source ptr inc ea. row mov cbIncS,ax mov ax,cbScanDst sub ax,bx ; cbIncD = dest ptr inc ea. row mov cbIncD,ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; caclulate the source/dest bitmap pointers ; ; ds:si --> source bitmap bits (pbSrc + cbScanSrc * SrcY + SrcX) ; es:di --> dest bitmap bits (pbDst + cbScanDst * DstY + DstX) ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; mov ax, DstY ; ax = start scan mul cbScanDst ; ax *= size of a scanline add ax, DstX ; ax += X offset adc dx, 0 ; dx = segment number mov di, ax ; set di = offset into segment add di, pbDst.off mov ax,dx ; set es = segment mov bx,__AHINCR mul bx add ax, pbDst.sel mov es,ax ; mov ax, SrcY ; ax = start scan mul cbScanSrc ; ax *= size of a scanline add ax, SrcX ; ax += X offset adc dx, 0 ; dx = segment number mov si, ax ; set si = offset into segment add si, pbSrc.off mov ax,dx ; set ds = segment mov bx,__AHINCR mul bx add ax, pbSrc.sel mov ds,ax assume ds:nothing ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; start a new row ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; RowLoop: xor ax,ax ; clear X error for start of line mov errx,ax mov errx+2,ax mov errx+4,ax mov errz,ax ; clear Z error for start of line mov errz+2,ax mov errz+4,ax mov ax,SrcXE ; sCol = number of cols to do mov sCol,ax xor bx,bx ; (bx) = initial column number ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; start of the column loop ; ; MOTE: bp is used in this loop!!! stack locals are not accessable. ; ; es:di --> dest bits ; ds:si --> source bits ; bx = Current column # * 6 ; bp = is *NOT* stack frame ; ss = DGROUP ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; push bp ColLoop: lodsb ; get a source BYTE xor ah,ah ; (ax) = dib color add ax,ax ; (ax) = 2 * dib color mov bp,ax ; (bp) = 2 * dib color add ax,ax ; (ax) = 4 * dib color add bp,ax ; (bp) = 6 * dib color (usPalMult index) mov cx,80H ; CL = lointens (MSB flag) xor ax,ax ; AL = output value irpc color,<420> mov dx,errz[color] ; move previous Z error to next Y xchg dx,erry[bx+color] ; and get this Y error add dx,usPalMult[bp+color] ; desired intensity of this color add dx,errx[color] ; plus X error mov v[color],dx ; save for ClrLoop2 cmp LoThresh,dx ; above low threshold? lahf ; set bit for this color accordingly rol ax,1 cmp HiThresh,dx ; above high threshold? lahf ; set bit for this color accordingly rol ax,1 cmp GrayThresh,dx ; above gray threshold? lahf ; AND together gray requirements and cl,ah endm or al,cl ; compose value ; (al) = Output color value ; (bx) = Column number * 6 ; (ss) = DGROUP stosb ; write a dest byte xor ah,ah add ax,ax mov bp,ax add ax,ax add bp,ax ; BP = input value * 6 (usPalMult index) cmp Prop,0 ;;jz NoProp irpc color,<420> mov ax,v[color] ; compute error for this color sub ax,sColorsOut[bp+color] imul Prop xor ax,dx ; ABS error sub ax,dx ;; shr ax,5 ; / 32 mov cx,ax shr cx,1 ; / 64 for Z xor ax,dx ; unABS error sub ax,dx ;; xor cx,dx ; unABS error sub cx,dx ;; add erry[bx+color],ax ; add Y error to previous Z mov errx[color],ax ; set X error mov errz[color],cx ; set Z error endm ; We get weird, below, trying to allow the common jump cases to fall ; through. Since ColLoop is so large, we will use the dead space ; after the unconditional jump to hide out-of-line code NoProp: or si,si jz fixSSeg fixDOff: or di,di jz fixDSeg EndColLoop: add bx,6 dec sCol jz ColLoopDone jmp ColLoop fixSSeg: mov ax,ds add ax,__AHINCR mov ds,ax jmp fixDOff fixDSeg: mov ax,es add ax,__AHINCR mov es,ax jmp EndColLoop ColLoopDone: ; End Weirdness. pop bp ; it is safe to use locals now add si,cbIncS jnc @f mov ax,ds add ax,__AHINCR mov ds,ax @@: add di,cbIncD jnc @f mov ax,es add ax,__AHINCR mov es,ax @@: dec SrcYE jz @F jmp RowLoop @@: cEnd sEnd CODE END