windows-nt/Source/XPSP1/NT/multimedia/media/avi/drawdib.16/dith775a.asm

1201 lines
35 KiB
NASM
Raw Normal View History

2020-09-26 03:20:57 -05:00
page ,132
;----------------------------Module-Header------------------------------;
; Module Name: DITH775.ASM
;
; code to dither 16 or 24 bit DIBs to a 8bit DIB with a fixed palette
;
; NOTES:
; this is a ASM version of the code found in dith775.c
;
;-----------------------------------------------------------------------;
?PLM=1
?WIN=0
.xlist
include cmacro32.inc
include windows.inc
.list
externA __AHINCR
externA __AHSHIFT
sBegin Data
externB _lookup775 ; in look775.h
externB _rdith775 ; in dtab775.h
externB _gdith775 ; in dtab775.h
sEnd Data
; 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
ifndef SEGNAME
SEGNAME equ <_TEXT>
endif
createSeg %SEGNAME, CodeSeg, word, public, CODE
sBegin CodeSeg
.386
assumes cs,CodeSeg
assumes ds,nothing
assumes es,nothing
;--------------------------------------------------------------------------;
;
; GET16 - read a RGB555 from the input
;
; INPUT:
; fs:[esi] rgb555 DIB
;
; OUTPUT:
; bx rgb555
;
;--------------------------------------------------------------------------;
GET16 macro col
if col and 1
shr ebx,16 ; get pel from last time
else
mov ebx, dword ptr fs:[esi] ; grab two pels
add esi,4
endif
endm
;--------------------------------------------------------------------------;
;
; DITH m1, m2, row, col
;
; grab a 16 bit pel and dither it.
;
; m1 and m2 are the magic dither table offsets.
;
; here is the 'C' code we are emulating
;
; w = *((WORD huge *)pbS)++;
; r = (int)((w >> 7) & 0xF8);
; g = (int)((w >> 2) & 0xF8);
; b = (int)((w << 3) & 0xF8);
;
; *pbD++ = (BYTE)lookup775[ rdith775[r + m1] + gdith775[g + m1] + ((b + m2) >> 6) ];
;
; the 'magic' values vary over a 4x4 block
;
; m1: 1 17 25 41 m2: 2 26 38 62
; 31 36 7 12 46 54 19 18
; 20 4 39 23 30 6 58 34
; 33 28 15 9 50 42 22 14
;
;
; for a 2x2 dither use the following numbers:
;
; m1: 5 27 m2: 8 40
; 38 16 56 24
;
; m1: 1 41 m2: 2 62
; 33 9 50 14
;
; NOTE:
; !!! the lookup tables should be BYTEs not INTs !!!
;
; Entry:
; m1, m2 - magic values
; fs:esi - 16bit pel to dither
; ds - data segment
;
; Returns:
; al - dithered pel (rotated into eax)
;
; Uses:
; eax, ebx, edx, ebp, esi, edi, flags
;
; Saves:
; ecx, edi, es,ds,fs,gs,ss
;
;--------------------------------------------------------------------------;
DITH16 macro m1, m2, row, col
GET16 col
mov al, bl ; get blue
and al, 1Fh
add al, (m2 shr 3)
shr al, 3
shr bx, 2 ; get green
mov dl, bl
and dx, 0F8h
shr bx, 5 ; get red
and bx, 0F8h
add al, _rdith775[bx + m1]
mov bl, dl
add al, _gdith775[bx + m1]
mov bl, al
if col and 1
mov al, byte ptr _lookup775[bx]
xchg al, ah
ror eax,16 ; rotate pixel into eax
else
mov ah, byte ptr _lookup775[bx]
endif
endm
;--------------------------------------------------------------------------;
;
; Dither16()
;
; Entry:
; Stack based parameters as described below.
;
; Returns:
; none
;
; Registers Preserved:
; DS,ES,ESI,EDI,EBP
;
;--------------------------------------------------------------------------;
assumes ds,Data
assumes es,nothing
Dither16TJumpTable label dword
dd Dither16Scan0
dd Dither16Scan3
dd Dither16Scan2
dd Dither16Scan1
cProc Dither16T,<FAR,PUBLIC,PASCAL>,<>
parmD biDst ;--> BITMAPINFO of dest
parmD lpDst ;--> to destination bits
parmW DstX ;Destination origin - x coordinate
parmW DstY ;Destination origin - y coordinate
parmW DstXE ;x extent of the BLT
parmW DstYE ;y extent of the BLT
parmD biSrc ;--> BITMAPINFO of source
parmD lpSrc ;--> to source bits
parmW SrcX ;Source origin - x coordinate
parmW SrcY ;Source origin - y coordinate
parmD lpDitherTable ;not used (for 8->4 bit dither)
localD SrcWidth ;width of source in bytes
localD DstWidth ;width of dest in bytes
localD SrcInc
localD DstInc
cBegin
push esi
push edi
; push ds
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; We only handle (DstXE % 4) == 0 or 3. If it's == 1 or 2, then we
; round down, because otherwise we'd have to deal with half of a
; dither cell on the end.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
inc DstXE ; Make the == 3 mod 4 case work
and DstXE, not 011b
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
mov eax,16
mov ebx,8
call dither_init ; init all the frame variables
jc Dither16Exit
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
movzx ecx, DstYE ; divide by 4
mov ebx, ecx
add ecx, 3 ; be sure to round up
shr ecx, 2
jz Dither16Exit
mov DstYE, cx
movzx ecx, DstXE ; divide by 4
shr ecx,2
jz Dither16Exit
mov DstXE,cx
and ebx, 011b ; Get height mod 4
jmp Dither16TJumpTable[ebx*4]
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
align 4
Dither16OuterLoop:
movzx ecx, DstXE
align 4
Dither16Scan0:
DITH16 1 2 0 0 ; DITH16 1 2 0 0
DITH16 17 26 0 1 ; DITH16 41 62 0 1
DITH16 25 38 0 2 ; DITH16 1 2 0 2
DITH16 41 62 0 3 ; DITH16 41 62 0 3
stos dword ptr es:[edi]
dec ecx
jnz Dither16Scan0
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither16Scan1:
DITH16 31 46 1 0 ; DITH16 33 50 1 0
DITH16 36 54 1 1 ; DITH16 9 14 1 1
DITH16 7 19 1 2 ; DITH16 33 50 1 2
DITH16 12 18 1 3 ; DITH16 9 14 1 3
stos dword ptr es:[edi]
dec ecx
jnz Dither16Scan1
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither16Scan2:
DITH16 20 30 2 0 ; DITH16 1 2 2 0
DITH16 4 6 2 1 ; DITH16 41 62 2 1
DITH16 39 58 2 2 ; DITH16 1 2 2 2
DITH16 23 34 2 3 ; DITH16 41 62 2 3
stos dword ptr es:[edi]
dec ecx
jnz Dither16Scan2
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither16Scan3:
DITH16 33 50 3 0 ; DITH16 33 50 3 0
DITH16 28 42 3 1 ; DITH16 9 14 3 1
DITH16 15 22 3 2 ; DITH16 33 50 3 2
DITH16 9 14 3 3 ; DITH16 9 14 3 3
stos dword ptr es:[edi]
dec ecx
jnz Dither16Scan3
add esi, SrcInc
add edi, DstInc
dec DstYE
jnz Dither16OuterLoop
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
Dither16Exit:
xor ax,ax
mov fs,ax ; to make KRNL286.EXE and DOSX happy
; pop ds
pop edi
pop esi
cEnd
;--------------------------------------------------------------------------;
;
; Dither16L() - dither using lookup table(s)
;
; using dither matrix:
;
; 0 2 2 4
; 3 4 0 1 [or possibly 3 3 1 1 -- see which looks better]
; 2 0 4 2
; 3 3 1 1
;
; the dither matrix determines which lookup table to use.
;
; Entry:
; Stack based parameters as described below.
;
; Returns:
; none
;
; Registers Preserved:
; DS,ES,ESI,EDI,EBP
;
;--------------------------------------------------------------------------;
assumes ds,Data
assumes es,nothing
FOO macro reg, err
if err eq 0
mov reg, ds:[ebx]
elseif err eq 1
mov reg, ds:[ebx + edx]
elseif err eq 2
mov reg, ds:[ebx + 2*edx]
elseif err eq 3
or bh,80h
mov reg, ds:[ebx + 2*edx]
elseif err eq 4
mov reg, ds:[ebx + 4*edx]
else
bark
endif
endm
DITH16L macro m1, m2, m3, m4
mov bx, fs:[esi + 4]
and bh, ch
FOO al, m3
mov bx, fs:[esi + 6]
and bh, ch
FOO ah, m4
shl eax,16
mov bx, fs:[esi + 0]
and bh, ch
FOO al, m1
mov bx, fs:[esi + 2]
and bh, ch
FOO ah, m2
mov dword ptr es:[edi], eax
add edi, 4
add esi, 8
endm
Dither16LJumpTable label dword
dd Dither16lScan0
dd Dither16lScan3
dd Dither16lScan2
dd Dither16lScan1
cProc Dither16L,<FAR,PUBLIC,PASCAL>,<>
parmD biDst ;--> BITMAPINFO of dest
parmD lpDst ;--> to destination bits
parmW DstX ;Destination origin - x coordinate
parmW DstY ;Destination origin - y coordinate
parmW DstXE ;x extent of the BLT
parmW DstYE ;y extent of the BLT
parmD biSrc ;--> BITMAPINFO of source
parmD lpSrc ;--> to source bits
parmW SrcX ;Source origin - x coordinate
parmW SrcY ;Source origin - y coordinate
parmD lpDitherTable ;196k dither table
localD SrcWidth ;width of source in bytes
localD DstWidth ;width of dest in bytes
localD SrcInc
localD DstInc
cBegin
push esi
push edi
push ds
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; We only handle (DstXE % 4) == 0 or 3. If it's == 1 or 2, then we
; round down, because otherwise we'd have to deal with half of a
; dither cell on the end.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
inc DstXE ; Make the == 3 mod 4 case work
and DstXE, not 011b
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
mov eax,16
mov ebx,8
call dither_init ; init all the frame variables
jc Dither16lExit
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
movzx ecx, DstYE ; divide by 4
mov ebx, ecx
add ecx, 3 ; be sure to round up
shr ecx, 2
jz Dither16lExit
mov DstYE, cx
movzx ecx, DstXE ; divide by 4
shr ecx,2
jz Dither16lExit
mov DstXE,cx
mov ds, lpDitherTable.sel ; DS --> dither table
mov ax, ds
add ax, __AHINCR
mov gs, ax
xor ebx, ebx
mov edx, 32768
mov ch,7Fh
and ebx, 011b ; Get height mod 4
jmp Dither16LJumpTable[ebx*4]
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
align 4
Dither16lOuterLoop:
mov cl, byte ptr DstXE
align 4
Dither16lScan0:
DITH16L 0 2 2 4
dec cl
jnz short Dither16lScan0
add esi, SrcInc
add edi, DstInc
mov cl, byte ptr DstXE
align 4
Dither16lScan1:
DITH16L 3 4 0 1
dec cl
jnz short Dither16lScan1
add esi, SrcInc
add edi, DstInc
mov cl, byte ptr DstXE
align 4
Dither16lScan2:
DITH16L 2 0 4 2
dec cl
jnz short Dither16lScan2
add esi, SrcInc
add edi, DstInc
mov cl, byte ptr DstXE
align 4
Dither16lScan3:
DITH16L 3 3 1 1
dec cl
jnz short Dither16lScan3
add esi, SrcInc
add edi, DstInc
dec DstYE
jnz Dither16lOuterLoop
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
Dither16lExit:
xor ax,ax
mov fs,ax ; to make KRNL286.EXE and DOSX happy
mov gs,ax
pop ds
pop edi
pop esi
cEnd
;--------------------------------------------------------------------------;
;
; Dither16S() - dither using scale table(s)
;
; pel8 = lookup[scale[rgb555] + error]
;
; using error matrix:
;
; 0 3283 4924 8207
; 6565 6566 1641 1642
; 3283 0 8207 4924
; 6566 4925 3282 1641
;
; Entry:
; Stack based parameters as described below.
;
; Returns:
; none
;
; Registers Preserved:
; DS,ES,ESI,EDI,EBP
;
;--------------------------------------------------------------------------;
assumes ds,Data
assumes es,nothing
DITH16S macro m1, m2, m3, m4
mov ebx, fs:[esi + 4] ; grab rgb555
add bx, bx
mov bx, ds:[bx] ; scale it
mov al, gs:[bx + m3] ; dither it with error
shr ebx,16
; mov bx, fs:[esi + 6] ; grab rgb555
add bx, bx
mov bx, ds:[bx] ; scale it
mov ah, gs:[bx + m4] ; dither it with error
shl eax,16
mov ebx, fs:[esi + 0] ; grab rgb555
add bx, bx
mov bx, ds:[bx] ; scale it
mov al, gs:[bx + m1] ; dither it with error
shr ebx,16
; mov bx, fs:[esi + 2] ; grab rgb555
add bx, bx
mov bx, ds:[bx] ; scale it
mov ah, gs:[bx + m2] ; dither it with error
mov dword ptr es:[edi], eax
add edi, 4
add esi, 8
endm
Dither16SJumpTable label dword
dd Dither16sScan0
dd Dither16sScan3
dd Dither16sScan2
dd Dither16sScan1
cProc Dither16S,<FAR,PUBLIC,PASCAL>,<>
parmD biDst ;--> BITMAPINFO of dest
parmD lpDst ;--> to destination bits
parmW DstX ;Destination origin - x coordinate
parmW DstY ;Destination origin - y coordinate
parmW DstXE ;x extent of the BLT
parmW DstYE ;y extent of the BLT
parmD biSrc ;--> BITMAPINFO of source
parmD lpSrc ;--> to source bits
parmW SrcX ;Source origin - x coordinate
parmW SrcY ;Source origin - y coordinate
parmD lpDitherTable ;196k dither table
localD SrcWidth ;width of source in bytes
localD DstWidth ;width of dest in bytes
localD SrcInc
localD DstInc
cBegin
push esi
push edi
push ds
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; align everything on four pixel boundries, we realy should
; not do this but should handle the general case instead,
; but hey we are hackers.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
inc DstXE ; Make the == 3 mod 4 case work
and DstXE, not 011b
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
mov eax,16
mov ebx,8
call dither_init ; init all the frame variables
jc Dither16sExit
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
movzx ecx, DstYE ; divide by 4
mov ebx, ecx
add ecx, 3 ; be sure to round up
shr ecx, 2
jz Dither16sExit
mov DstYE, cx
movzx ecx, DstXE ; divide by 4
shr ecx,2
jz Dither16sExit
mov DstXE,cx
mov ds, lpDitherTable.sel ; DS --> dither table
mov ax, ds
add ax, __AHINCR
mov gs, ax
and ebx, 011b ; Get height mod 4
jmp Dither16SJumpTable[ebx*4]
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
align 4
Dither16sOuterLoop:
movzx ecx, DstXE
align 4
Dither16sScan0:
DITH16S 0 3283 4924 8207
dec ecx
jnz short Dither16sScan0
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither16sScan1:
DITH16S 6565 6566 1641 1642
dec ecx
jnz short Dither16sScan1
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither16sScan2:
DITH16S 3283 0 8207 4924
dec ecx
jnz short Dither16sScan2
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither16sScan3:
DITH16S 6566 4925 3282 1641
dec ecx
jnz short Dither16sScan3
add esi, SrcInc
add edi, DstInc
dec DstYE
jnz Dither16sOuterLoop
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
Dither16sExit:
xor ax,ax
mov fs,ax ; to make KRNL286.EXE and DOSX happy
mov gs,ax
pop ds
pop edi
pop esi
cEnd
;--------------------------------------------------------------------------;
;
; LODSB32 - get a byte, every four times doing a LODSD
;
;--------------------------------------------------------------------------;
LODSB32_N = 0
LODSB32 macro
if (LODSB32_N mod 4) eq 0
;; lods dword ptr ds:[esi]
mov eax,dword ptr fs:[esi]
add esi,4
else
ror eax,8
endif
LODSB32_N = LODSB32_N + 1
endm
;--------------------------------------------------------------------------;
;
; Dither24S() - dither using scale table(s)
;
; pel8 = lookup[scale[rgb555] + error]
;
; using error matrix:
;
; 0 3283 4924 8207
; 6565 6566 1641 1642
; 3283 0 8207 4924
; 6566 4925 3282 1641
;
; Entry:
; Stack based parameters as described below.
;
; Returns:
; none
;
; Registers Preserved:
; DS,ES,ESI,EDI,EBP
;
;--------------------------------------------------------------------------;
assumes ds,Data
assumes es,nothing
GET24 macro
LODSB32 ; get BLUE
and al,0F8h
mov bl,al
LODSB32 ; get GREEN
mov bh,al
shr bh,3
shr ebx,2
LODSB32 ; get RED
and al,0F8h
or bh,al
endm
DITH24S macro m1, m2, m3, m4
GET24 ; grab rgb555*2
movzx ebx, word ptr ds:[ebx] ; scale it
mov dl, ds:[ebx + m1 + 65536] ; dither it with error
GET24 ; grab rgb555*2
movzx ebx, word ptr ds:[ebx] ; scale it
mov dh, ds:[ebx + m2 + 65536] ; dither it with error
ror edx,16 ; save ax
GET24 ; grab rgb555
movzx ebx, word ptr ds:[ebx] ; scale it
mov dl, ds:[ebx + m3 + 65536] ; dither it with error
GET24 ; grab rgb555
movzx ebx, word ptr ds:[ebx] ; scale it
mov dh, ds:[ebx + m4 + 65536] ; dither it with error
ror edx,16 ; get eax right
mov dword ptr es:[edi], edx ; store four pixels
add edi, 4
endm
Dither24SJumpTable label dword
dd Dither24sScan0
dd Dither24sScan3
dd Dither24sScan2
dd Dither24sScan1
cProc Dither24S,<FAR,PUBLIC,PASCAL>,<>
parmD biDst ;--> BITMAPINFO of dest
parmD lpDst ;--> to destination bits
parmW DstX ;Destination origin - x coordinate
parmW DstY ;Destination origin - y coordinate
parmW DstXE ;x extent of the BLT
parmW DstYE ;y extent of the BLT
parmD biSrc ;--> BITMAPINFO of source
parmD lpSrc ;--> to source bits
parmW SrcX ;Source origin - x coordinate
parmW SrcY ;Source origin - y coordinate
parmD lpDitherTable ;196k dither table
localD SrcWidth ;width of source in bytes
localD DstWidth ;width of dest in bytes
localD SrcInc
localD DstInc
cBegin
push esi
push edi
push ds
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; align everything on four pixel boundries, we realy should
; not do this but should handle the general case instead,
; but hey we are hackers.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; inc DstXE ; Make the == 3 mod 4 case work
and DstXE, not 011b
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
mov eax,24
mov ebx,8
call dither_init ; init all the frame variables
jc Dither24sExit
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
movzx ecx, DstYE ; divide by 4
mov ebx, ecx
add ecx, 3 ; be sure to round up
shr ecx, 2
jz Dither24sExit
mov DstYE, cx
movzx ecx, DstXE ; divide by 4
shr ecx,2
jz Dither24sExit
mov DstXE,cx
mov ds, lpDitherTable.sel ; DS --> dither table
mov ax, ds
add ax, __AHINCR
mov gs, ax
and ebx, 011b ; Get height mod 4
jmp Dither24SJumpTable[ebx*4]
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
align 4
Dither24sOuterLoop:
movzx ecx, DstXE
align 4
Dither24sScan0:
DITH24S 0 3283 4924 8207
dec ecx
jnz Dither24sScan0
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither24sScan1:
DITH24S 6565 6566 1641 1642
dec ecx
jnz Dither24sScan1
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither24sScan2:
DITH24S 3283 0 8207 4924
dec ecx
jnz Dither24sScan2
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither24sScan3:
DITH24S 6566 4925 3282 1641
dec ecx
jnz Dither24sScan3
add esi, SrcInc
add edi, DstInc
dec DstYE
jnz Dither24sOuterLoop
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
Dither24sExit:
xor ax,ax
mov fs,ax ; to make KRNL286.EXE and DOSX happy
mov gs,ax
pop ds
pop edi
pop esi
cEnd
;--------------------------------------------------------------------------;
;
; Dither32S() - dither using scale table(s)
;
; pel8 = lookup[scale[rgb555] + error]
;
; using error matrix:
;
; 0 3283 4924 8207
; 6565 6566 1641 1642
; 3283 0 8207 4924
; 6566 4925 3282 1641
;
; Entry:
; Stack based parameters as described below.
;
; Returns:
; none
;
; Registers Preserved:
; DS,ES,ESI,EDI,EBP
;
;--------------------------------------------------------------------------;
assumes ds,Data
assumes es,nothing
GET32 macro
if 1
mov bx,fs:[esi+0] ; ebx = ????????????????GGGGGgggBBBBBbbb
shr bh,3 ; ebx = 000?????????????000GGGGGBBBBBbbb
shr bx,3 ; ebx = 000?????????????000000GGGGGBBBBB
mov al,fs:[esi+2] ; eax = ????????????????????????RRRRRrrr
and al,0F8h ; eax = ????????????????????????RRRRR000
shr al,1 ; eax = ????????????????????????0RRRRR00
or bh,al ; ebx = 000?????????????0RRRRRGGGGGBBBBB
add ebx,ebx ; ebx = 00?????????????0RRRRRGGGGGBBBBB0
add esi,4
else
mov eax,fs:[esi] ; eax = RRRRRrrrGGGGGgggBBBBBbbb
add esi,2
mov bl,al ; ebx = 00000000????????BBBBBbbb
shr eax,8 ; eax = 00000000RRRRRrrrGGGGGggg
shr ah,3 ; eax = 00000000000RRRRRGGGGGggg
shl ax,5 ; eax = 000000RRRRRGGGGGggg00000
endif
endm
DITH32S macro m1, m2, m3, m4
GET32 ; grab rgb555*2
mov bx, word ptr ds:[ebx] ; scale it
mov dl, ds:[ebx + m1 + 65536] ; dither it with error
GET32 ; grab rgb555*2
mov bx, word ptr ds:[ebx] ; scale it
mov dh, ds:[ebx + m2 + 65536] ; dither it with error
ror edx,16 ; save ax
GET32 ; grab rgb555
mov bx, word ptr ds:[ebx] ; scale it
mov dl, ds:[ebx + m3 + 65536] ; dither it with error
GET32 ; grab rgb555
movzx bx, word ptr ds:[ebx] ; scale it
mov dh, ds:[ebx + m4 + 65536] ; dither it with error
ror edx,16 ; get eax right
mov dword ptr es:[edi], edx ; store four pixels
add edi, 4
endm
Dither32SJumpTable label dword
dd Dither32sScan0
dd Dither32sScan3
dd Dither32sScan2
dd Dither32sScan1
cProc Dither32S,<FAR,PUBLIC,PASCAL>,<>
parmD biDst ;--> BITMAPINFO of dest
parmD lpDst ;--> to destination bits
parmW DstX ;Destination origin - x coordinate
parmW DstY ;Destination origin - y coordinate
parmW DstXE ;x extent of the BLT
parmW DstYE ;y extent of the BLT
parmD biSrc ;--> BITMAPINFO of source
parmD lpSrc ;--> to source bits
parmW SrcX ;Source origin - x coordinate
parmW SrcY ;Source origin - y coordinate
parmD lpDitherTable ;196k dither table
localD SrcWidth ;width of source in bytes
localD DstWidth ;width of dest in bytes
localD SrcInc
localD DstInc
cBegin
push esi
push edi
push ds
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; align everything on four pixel boundries, we realy should
; not do this but should handle the general case instead,
; but hey we are hackers.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; inc DstXE ; Make the == 3 mod 4 case work
and DstXE, not 011b
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
mov eax,32
mov ebx,8
call dither_init ; init all the frame variables
jc Dither32sExit
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
movzx ecx, DstYE ; divide by 4
mov ebx, ecx
add ecx, 3 ; be sure to round up
shr ecx, 2
jz Dither32sExit
mov DstYE, cx
movzx ecx, DstXE ; divide by 4
shr ecx,2
jz Dither32sExit
mov DstXE,cx
mov ds, lpDitherTable.sel ; DS --> dither table
mov ax, ds
add ax, __AHINCR
mov gs, ax
and ebx, 011b ; Get height mod 4
jmp Dither32SJumpTable[ebx*4]
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
align 4
Dither32sOuterLoop:
movzx ecx, DstXE
align 4
Dither32sScan0:
DITH32S 0 3283 4924 8207
dec ecx
jnz Dither32sScan0
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither32sScan1:
DITH32S 6565 6566 1641 1642
dec ecx
jnz Dither32sScan1
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither32sScan2:
DITH32S 3283 0 8207 4924
dec ecx
jnz Dither32sScan2
add esi, SrcInc
add edi, DstInc
movzx ecx, DstXE
align 4
Dither32sScan3:
DITH32S 6566 4925 3282 1641
dec ecx
jnz Dither32sScan3
add esi, SrcInc
add edi, DstInc
dec DstYE
jnz Dither32sOuterLoop
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
Dither32sExit:
xor ax,ax
mov fs,ax ; to make KRNL286.EXE and DOSX happy
mov gs,ax
pop ds
pop edi
pop esi
cEnd
;--------------------------------------------------------------------------;
;
; dither_init
;
; init local frame vars for DitherDIB
;
; ENTRY:
; AX - source bpp
; BX - dest bpp
; ss:bp --> ditherdib frame
;
; EXIT:
; FS:ESI --> source DIB start x,y
; ES:EDI --> dest DIB start x,y
; DS: --> dither tables (in DGROUP)
;
;--------------------------------------------------------------------------;
dither_init_error:
stc
ret
dither_init proc near
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; validate the DIBs
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
movzx eax,ax
movzx ebx,bx
movzx ecx,cx
movzx edx,dx
movzx edi,di
movzx esi,si
lfs si, biSrc
les di, biDst
mov cx, es:[di].biBitCount ; dest must be right
cmp cx, bx
jne dither_init_error
mov cx, fs:[si].biBitCount ; source must be right
cmp cx, ax
jne dither_init_error
dither_init_bit_depth_ok:
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
;
; Set up the initial source pointer
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
mov eax,fs:[si].biWidth
mul ecx
add eax,31
and eax,not 31
shr eax,3
mov SrcWidth,eax
mov SrcInc,eax
lfs si,lpSrc
movzx edx,SrcY
mul edx
add esi,eax
movzx eax,SrcX
mul ecx
shr eax,3
add esi,eax
movzx eax, DstXE ; SrcInc = SrcWidth - DstXE*bits/8
mul ecx
shr eax, 3
sub SrcInc, eax
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
;
; Set up the initial dest pointer
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
mov cx, es:[di].biBitCount
mov eax,es:[di].biWidth
mul ecx
add eax,31
and eax,not 31
shr eax,3
mov DstWidth,eax
mov DstInc,eax
cmp es:[edi].biHeight,0 ; init a upside down DIB
jge short @f
movsx ebx,DstY
add ebx,es:[edi].biHeight
not ebx
mov DstY,bx
neg DstWidth
neg DstInc
@@:
les di,lpDst
movsx edx,DstY
mul edx
add edi,eax
movsx eax,DstX
mul ecx
shr eax,3
add edi,eax
movzx eax, DstXE ; DstInc = DstWidth - DstXE*bits/8
mul ecx
shr eax, 3
sub DstInc, eax
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
dither_init_exit:
clc
ret
dither_init endp
sEnd CodeSeg
end