;***************************************************************************
; unit:    raster      release 0.21                                        *
; purpose: general manipulation n dimensional matrices n = 1, 2 and 3.     *
;          Use this file or rasterc.c. You cannot link both files together *
; licency:     GPL or LGPL                                                 *
; Copyright: (c) 2021-2021 Jaroslav Fojtik                                 *
;***************************************************************************

.CODE             ;Indicates the start of a code segment.



;void Conv1_4(BYTE *Dest, const BYTE *Src, unsigned Size1D)
        public  Conv1_4
Conv1_4 proc \
        uses rdi rsi
;       Dest:ptr byte, \
;       Src:ptr byte, \
;       count:DWORD

        mov     rdi,rcx		; rdi=destination pointer
	mov	rcx,R8		; R8=amount of pixels
	or	rcx,rcx
        jz	ToEnd     ; it's as if strings are equal
        mov     rsi,rdx		; rsi=source pointer

octet:  mov     al,[rsi]	; new octet

	cbw			; Extend 8th bit to AH	

	dec	rcx
	mov	dl,ah
        jz      ToEndNbl
        and	dl,0F0h		; mask low nibble
        
        rol     al,1		; 40h
        cbw			; Extend 7th bit to AH
        and	ah,0Fh		; mask high nibble		
        or	ah,dl
	mov	[rdi],ah	; store converted byte

	dec	rcx
        jz      ToEnd
	inc	rdi      
        
        rol     al,1		; 20h
        cbw			; Extend 6th bit to AH	

	dec	rcx
	mov	dl,ah
        jz      ToEndNbl
        and	dl,0F0h		; mask low nibble
        
        rol     al,1		; 10h
        cbw			; Extend 5th bit to AH
        and	ah,0Fh
        or	ah,dl	
	mov	[rdi],ah	; store converted byte

	dec	rcx
        jz      ToEnd
	inc	rdi   

        rol     al,1		; 08h
        cbw			; Extend 4th bit to AH	

	dec	rcx
	mov	dl,ah
        jz      ToEndNbl
        and	dl,0F0h		; mask low nibble
        
        rol     al,1		; 04h
	cbw			; Extend 3rd bit to AH
        and	ah,0Fh
        or	ah,dl	
	mov	[rdi],ah	; store converted byte

	dec	rcx
        jz      ToEnd
	inc	rdi        
        
        rol     al,1		; 02h
        cbw			; Extend 2nd bit to AH

	dec	rcx
	mov	dl,ah
        jz      ToEndNbl
        and	dl,0F0h		; mask low nibblde
        
        rol     al,1		; 01h
        cbw			; Extend 1st bit to AH
	and	ah,0Fh
        or	ah,dl	        
	mov	[rdi],ah	; store converted byte
	
	inc	rsi
	inc	rdi

	dec	rcx
	jne	octet

ToEnd:
        ret                     ; _cdecl return
        
ToEndNbl:
	and	ah,0F0h
	mov	[rdi],ah	; store converted low nibble
	ret        
        
Conv1_4 endp


;*************************************************************************************


;void Conv1_8(BYTE *Dest, const BYTE *Src, unsigned Size1D)
        public  Conv1_8
Conv1_8 proc \
        uses rdi rsi
;       Dest:ptr byte,	RCX
;       Src:ptr byte,	RDX
;       count:DWORD	R8

        mov     rdi,rcx		; rdi=destination pointer
	mov	rcx,R8		; R8=amount of pixels
        mov     rsi,rdx		; rsi=source pointer
        or	rcx,rcx
        jz	toend		; it's as if strings are equal

octet:  mov     al,[rsi]	; new octet        

	cbw			; Extend 8th bit to AH
	mov	[rdi],ah	; store converted byte	

	dec	rcx
        jz      toend
	inc	rdi
        
        rol     al,1		; 40h
        cbw			; Extend 7th bit to AH
	mov	[rdi],ah	; store converted byte	

	dec	rcx
        jz      toend
	inc	rdi
        
        rol     al,1		; 20h
        cbw			; Extend 6th bit to AH
	mov	[rdi],ah	; store converted byte

	dec	rcx
        jz      toend
	inc	rdi
        
        rol     al,1		; 10h
        cbw			; Extend 5th bit to AH
	mov	[rdi],ah	; store converted byte

	dec	rcx
        jz      toend
	inc	rdi

        rol     al,1		; 08h
        cbw			; Extend 4th bit to AH
	mov	[rdi],ah	; store converted byte

	dec	rcx
        jz      toend
	inc	rdi
        
        rol     al,1		; 04h
	cbw			; Extend 3rd bit to AH
	mov	[rdi],ah	; store converted byte

	dec	rcx
        jz      toend
	inc	rdi
        
        rol     al,1		; 02h
        cbw			; Extend 2nd bit to AH
	mov	[rdi],ah	; store converted byte

	dec	rcx
        jz      toend
	inc	rdi
        
        rol     al,1		; 01h
        cbw			; Extend 1st bit to AH
	mov	[rdi],ah	; store converted byte

	inc	rsi
	inc	rdi

	dec	rcx
	jne	octet

toend:
        ret                     ; _cdecl return

Conv1_8 endp


;*************************************************************************************

        public  Conv1_16
Conv1_16 proc \
        uses rdi rsi
;       Dest:ptr byte,	RCX
;       Src:ptr byte,	RDX
;       count:DWORD	R8

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        mov     rsi,rdx		; rdx second pointer
        or	rcx,rcx
        jz	toend		; array has zero size

Octet:  mov     ah,[rsi]	; new octet
        
        cwd			; extend 8th bit to DX
        mov	[rdi],dx

	dec	rcx
        jz      toend
        add	rdi,2
        
        rol	ax,1        
        cwd			; extend 7th bit to DX
        mov	[rdi],dx

	dec	rcx
        jz      toend
        add	rdi,2
        
        rol	ax,1        
        cwd			; extend 6th bit to DX
        mov	[rdi],dx

	dec	rcx
        jz      toend
        add	rdi,2
        
        rol	ax,1        
        cwd			; extend 5th bit to DX
        mov	[rdi],dx

	dec	rcx
        jz      toend
        add	rdi,2

        rol	ax,1        
        cwd			; extend 4th bit to DX
        mov	[rdi],dx

	dec	rcx
        jz      toend
        add	rdi,2        
        
        rol	ax,1        
        cwd			; extend 3rd bit to DX
        mov	[rdi],dx

	dec	rcx
        jz      toend
        add	rdi,2
        
        rol	ax,1        
        cwd			; extend 2nd bit to DX
        mov	[rdi],dx

	dec	rcx
        jz      toend
        add	rdi,2
        
        rol	ax,1        
        cwd			; extend 1st bit to DX
        mov	[rdi],dx

        inc	rsi
        add	rdi,2

	dec	rcx
	jnz	Octet

toend:
        ret                     ; _cdecl return

Conv1_16 endp



;void Conv1_24(BYTE *Dest, const BYTE *Src, unsigned Size1D)
        public  Conv1_24
Conv1_24 proc \
        uses rdi rsi
;       Dest:ptr byte,	RCX
;       Src:ptr byte,	RDX
;       count:DWORD	R8

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        mov     rsi,rdx		; rdx second destination pointer
        or	rcx,rcx
        jz	toend		; array has zero size

octet:  mov     ah,[rsi]	; new octet

	cwd			; Extend 8th bit to DX
	mov	[rdi],dx	; store converted byte
	add	rdi,2
	mov	[rdi],dl
	inc	rdi

	dec	rcx
        jz      toend
        
        rol     ax,1		; 40h
        cwd			; Extend 7th bit to DX
	mov	[rdi],dl	; store converted byte
	inc	rdi
	mov	[rdi],dx
	add	rdi,2

	dec	rcx
        jz      toend
        
        rol     ax,1		; 20h
        cwd			; Extend 6th bit to DX
	mov	[rdi],dx	; store converted byte
	add	rdi,2
	mov	[rdi],dl
	inc	rdi	

	dec	rcx
        jz      toend
        
        rol     ax,1		; 10h
        cwd			; Extend 5th bit to DX
	mov	[rdi],dl	; store converted byte
	inc	rdi
	mov	[rdi],dx
	add	rdi,2

	dec	rcx
        jz      toend

        rol     ax,1		; 08h
        cwd			; Extend 4th bit to DX
	mov	[rdi],dx	; store converted byte
	add	rdi, 2
	mov	[rdi],dl
	inc	rdi

	dec	rcx
        jz      toend
        
        rol     ax,1		; 04h
	cwd			; Extend 3rd bit to AH
	mov	[rdi],dl	; store converted byte
	inc	rdi
	mov	[rdi],dx
	add	rdi,2

	dec	rcx
        jz      toend
        
        rol     ax,1		; 02h
        cwd			; Extend 2nd bit to DX
	mov	[rdi],dx	; store converted byte
	add	rdi,2
	mov	[rdi],dl	
	inc	rdi        

	dec	rcx
        jz      toend
        
        rol     ax,1		; 01h
        cwd			; Extend 1st bit to DX
	mov	[rdi],dl	; store converted byte
	inc	rdi
	mov	[rdi],dx
	add	rdi, 2	
	
	inc	rsi

	dec	rcx
	jne	octet

toend:
        ret                     ; _cdecl return

Conv1_24 endp


;*************************************************************************************

        public  Conv1_32
Conv1_32 proc \
        uses rdi rsi
;       Dest:ptr byte,	RCX
;       Src:ptr byte,	RDX
;       count:DWORD	R8

	mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        or	rcx,rcx
        jz	toend		; array has zero size

        mov     rsi,rdx		; rdx second pointer        

	cld
Octet:  mov     ah,[rsi]	; new octet
        
        shl	eax,16
	cdq			; extend 8th bit to EDX
        mov	[rdi],edx

	dec	rcx
        jz      toend
        add	rdi,4
        
        rol	eax,1        
        cdq			; extend 7th bit to EDX
        mov	[rdi],edx

	dec	rcx
        jz      toend
        add	rdi,4
        
        rol	eax,1        
        cdq			; extend 6th bit to EDX
        mov	[rdi],edx

	dec	rcx
        jz      toend
        add	rdi,4
        
        rol	eax,1        
        cdq			; extend 5th bit to EDX
        mov	[rdi],edx        

	dec	rcx
        jz      toend
	add	rdi,4

        rol	eax,1        
        cdq			; extend 4th bit to EDX
        mov	[rdi],edx

	dec	rcx
        jz      toend
        add	rdi,4       
        
        rol	eax,1        
        cdq			; extend 3rd bit to EDX
        mov	[rdi],edx

	dec	rcx
        jz      toend
        add	rdi,4
        
        rol	eax,1        
        cdq			; extend 2nd bit to EDX
        mov	[rdi],edx        

	dec	rcx
        jz      toend
        add	rdi,4
        
        rol	eax,1        
        cdq			; extend 1st bit to EDX
        mov	[rdi],edx

        inc	rsi
        add	rdi,4

	dec	rcx
	jnz	Octet

toend:
        ret                     ; _cdecl return

Conv1_32 endp


;*************************************************************************************


        public  Conv1_64
Conv1_64 proc \
        uses rdi rsi
;       Dest:ptr byte,	RCX
;       Src:ptr byte,	RDX
;       count:DWORD	R8

	mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        or	rcx,rcx
        jz	toend		; array has zero size

        mov     rsi,rdx		; rdx second pointer        

Octet:  mov     ah,[rsi]	; new octet

	shl	rax,48        
        cqo			; extend 8th bit to RDX
        mov	[rdi],rdx

	dec	rcx
        jz      toend
        add	rdi,8
        
        rol	rax,1        
        cqo			; extend 7th bit to RDX
        mov	[rdi],rdx

	dec	rcx
        jz      toend
        add	rdi,8
        
        rol	rax,1        
        cqo			; extend 6th bit to RDX
        mov	[rdi],rdx

	dec	rcx
        jz      toend
        add	rdi,8
        
        rol	rax,1        
        cqo			; extend 5th bit to RDX
        mov	[rdi],rdx

	dec	rcx
        jz      toend
        add	rdi,8

        rol	rax,1        
        cqo			; extend 4th bit to DX
        mov	[rdi],rdx

	dec	rcx
        jz      toend
        add	rdi,8
                
        rol	rax,1
        cqo			; extend 3rd bit to DX
        mov	[rdi],rdx

	dec	rcx
        jz      toend
        add	rdi,8
        
        rol	rax,1        
        cqo			; extend 2nd bit to DX
        mov	[rdi],rdx

	dec	rcx
        jz      toend
        add	rdi,8
        
        rol	rax,1        
        cqo			; extend 1st bit to DX
        mov	[rdi],rdx

        inc	rsi
        add	rdi,8

	dec	rcx
	jnz	Octet

toend:
        ret                     ; _cdecl return

Conv1_64 endp


;*************************************************************************************
;*************************************************************************************


;void Conv4_1(BYTE *Dest, const BYTE *Src, unsigned Size1D)
        public  Conv4_1
Conv4_1 proc \
        uses rdi rsi
;       Dest:ptr byte,	RCX
;       Src:ptr byte,	RDX
;       count:DWORD	R8

	mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; rdx second pointer        
        
        cld        
        mov	ah,1		; add end byte mark
PIXEL:	lodsb
	rol	al,1		; copy the highest bit to CY
	rcl	ah,1		; transfer bit from CY to AH
	
	dec	rcx		; 2nd nibble
	jz	First1
	rol	al,4		; copy original 4th bit to CY
	rcl	ah,1		; transfer bit from CY to AH
			
	jnc	NoOctet			
	mov	[rdi],ah	; Full 8 bits finished, 1 travelled to CY.
	inc	rdi
	mov	ah,1		; add end byte mark
	loop	PIXEL
	jmp	toend		; all done here
	
NoOctet:loop	PIXEL

First1:	sal	ah,1		; shift must be finished to 8th bit
	jnc	First1
	mov	[rdi],ah	; store last incomplete byte

toend:
        ret                     ; _cdecl return
                
Conv4_1 endp



;void Conv4_8(BYTE *Dest, const BYTE *Src, unsigned Size1D)
        public  Conv4_8
Conv4_8 proc \
        uses rdi rsi rbx
;       Dest:ptr byte,	RCX
;       Src:ptr byte,	RDX
;       count:DWORD	R8

	mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; rdx second pointer        
        cld
PIXEL:	lodsb
        mov	bl,al
	mov	ah,al
	and	al,0F0h		; copy the highest bit to CY
	shr	ah,4
	or	al,ah		; byte from 1st nibble finished
	stosb

	dec	rcx		; 2nd nibble
	jz	toend

	mov	al,bl
	and	al,0Fh
	sal	bl,4
	or	al,bl		; byte from 2nd nibble finished
	stosb
NoOctet:loop	PIXEL

toend:
        ret                     ; _cdecl return
                
Conv4_8 endp



;void Conv4_16(WORD *Dest, const BYTE *Src, unsigned Size1D)
        public  Conv4_16
Conv4_16 proc \
	uses rdi rsi rbx, \
;       Dest:ptr byte,	RCX
;       Src:ptr byte,	RDX
;       count:DWORD	R8        

        mov     rdi,rcx		; rdi = destination pointer

	mov     rcx,R8		; rcx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; rsi = source pointer
        
        cld
PIXEL:	lodsb
        mov	bl,al
	mov	ah,al
	and	al,0F0h		; copy the highest bit to CY
	shr	ah,4
	or	al,ah		; byte from 1st nibble finished
	mov	ah,al
	stosw

	dec	rcx		; 2nd nibble
	jz	toend

	mov	al,bl
	and	al,0Fh
	sal	bl,4
	or	al,bl		; byte from 2nd nibble finished
	mov	ah,al
	stosw
NoOctet:loop	PIXEL

toend:
        ret                     ; _cdecl return
                
Conv4_16 endp



;void Conv4_32(DWORD *Dest, const BYTE *Src, unsigned Size1D)
        public  Conv4_32
Conv4_32 proc \
	uses rdi rsi rbx
;       Dest:ptr byte,	RCX
;       Src:ptr byte,	RDX
;       count:DWORD	R8

        mov     rdi,rcx		; rdi = destination pointer

        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; rsi = source pointer
        
        cld
PIXEL:	lodsb
        mov	bl,al
	mov	ah,al
	and	al,0F0h		; copy the highest bit to CY
	shr	ah,4
	or	al,ah		; byte from 1st nibble finished
	mov	ah,al	
	stosw
	stosw

	dec	rcx		; 2nd nibble
	jz	toend

	mov	al,bl
	and	al,0Fh
	sal	bl,4
	or	al,bl		; byte from 2nd nibble finished
	mov	ah,al
	mov	bx,ax
	shl	eax,16
	mov	ax,bx		; dword from 2nd nibble finished
	stosd
NoOctet:loop	PIXEL

toend:
        ret                     ; _cdecl return
                
Conv4_32 endp




;*************************************************************************************
;*************************************************************************************

        public  Conv8_1
Conv8_1 proc \
	uses rdi rsi rbx       
;       Dest:ptr qword
;       Src:ptr byte
;       count:DWORD

	mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size
        
        mov     rsi,rdx		;
        
        cld        
        mov	ah,1		; add end byte mark
PIXEL:	lodsb
	rol	al,1		; copy the highest bit to CY
	rcl	ah,1		; transfer bit from CY
	jnc	NoOctet
	mov	[rdi],ah
	inc	rdi
	mov	ah,1		; add end byte mark
	loop	PIXEL
	jmp	toend		; all done here
	
NoOctet:loop	PIXEL

First1:	sal	ah,1		; shift must be finished to 8th bit
	jnc	First1
	mov	[rdi],ah	; store last incomplete byte

toend:
        ret                     ; _cdecl return
                
Conv8_1 endp


;*************************************************************************************


        public  Conv8_4
Conv8_4 proc \
        uses rdi rsi
;       Dest:ptr byte,
;       Src:ptr byte,
;       count:DWORD
        
	mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size
        
        mov     rsi,rdx		;
        
        cld
PIXEL:	lodsb			; load 1st byte
	and	al,0F0h
	
	dec	rcx
	jnz	NIBBLE2
	stosb			;store incomplete nibble
	jmp	toend

NIBBLE2:mov	ah,al
        lodsb			; load 2nd byte
        and	al,0F0h
	ror	al,4
	or	al,ah
	stosb			;store both nibbles
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv8_4 endp



;*************************************************************************************


        public  Conv8_16
Conv8_16 proc \
	uses rdi rsi rbx        
;       Dest:ptr qword, \
;       Src:ptr byte, \
;       count:DWORD

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		;
        
        cld
PIXEL4: cmp	rcx,4	
        jl	PIXEL
       
        lodsd			; pixels 1,2,3,4
        mov	ebx,eax
        
        mov	al,bh
        sal	eax,16
        mov	ah,bl
        mov	al,bl
        stosd			; converted pixel 1 & 2
        
        shr	ebx,16
        mov	al,bh
        mov	ah,bh
        sal	eax,16
        mov	ah,bl
        mov	al,bl
        stosd			; converted pixel 3 & 4
        
        sub	rcx,4
        jnz	PIXEL4
        jmp	ToEnd
                
PIXEL:	lodsb
	mov	ah,al
	stosw
	loop	PIXEL
        
ToEnd:	ret			; _cdecl return
                
Conv8_16 endp


;*************************************************************************************

        public  Conv8_24
Conv8_24 proc \
        uses rdi rsi
;       Dest:ptr qword,
;       Src:ptr byte,
;       count:DWORD

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		;
        
        cld
PIXEL:	lodsb	
	stosb
	stosb
	stosb
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv8_24 endp


;*************************************************************************************

        public  Conv8_32
Conv8_32 proc \
        uses rdi rsi
;       Dest:ptr qword, \
;       Src:ptr byte, \
;       count:DWORD

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		;
        
        cld
PIXEL:	lodsb
	mov	ah,al
	mov	dx,ax
	rol	eax,16
	mov	ax,dx
	stosd
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv8_32 endp


;*************************************************************************************

        public  Conv8_64
Conv8_64 proc \
	uses rdi rsi rbx
;       Dest:ptr qword, \
;       Src:ptr byte, \
;       count:DWORD

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		;
        
        cld
PIXEL:	lodsb
	mov	ah,al
	mov	bx,ax
	rol	eax,16
	mov	ax,bx
	stosd
	stosd
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv8_64 endp


;*************************************************************************************
;*************************************************************************************

        public  Conv16_1
Conv16_1 proc \
        uses rdi rsi rbx
;       Dest:ptr byte, \
;       Src:ptr word, \
;       count:DWORD

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8             ; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		;
        
        cld        
        mov	bl,1		; add end byte mark
PIXEL:	lodsw
	rol	ax,1		; copy the highest bit to CY
	rcl	bl,1		; transfer bit from CY
	jnc	NoOctet
	mov	[rdi],bl
	inc	rdi
	mov	bl,1		; add end byte mark
	loop	PIXEL
	jmp	toend		; all done here
	
NoOctet:loop	PIXEL

First1:	sal	bl,1		; shift must be finished to 8th bit
	jnc	First1
	mov	[rdi],bl	; store last incomplete byte

toend:
        ret                     ; _cdecl return
                
Conv16_1 endp



;*************************************************************************************


        public  Conv16_4
Conv16_4 proc \
        uses rdi rsi
;       Dest:ptr byte, \
;       Src:ptr word, \
;       count:DWORD

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		;
        
        cld
PIXEL:	inc	si
	lodsb			; load 1st hi byte
	and	al,0F0h
	
	dec	rcx
	jnz	NIBBLE2
	stosb			;store incomplete nibble
	jmp	toend

NIBBLE2:mov	ah,al
	inc	si
        lodsb			; load 2nd byte
        and	al,0F0h
	ror	al,4
	or	al,ah
	stosb			;store both nibbles
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv16_4 endp



;*************************************************************************************


        public  Conv16_8
Conv16_8 proc \
        uses rdi rsi rbx
;       Dest:ptr qword, \
;       Src:ptr byte, \
;       count:DWORD

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	ToEnd		; array has zero size
        
        mov     rsi,rdx		;
        
        cld
PIXEL4: cmp	rcx,4
        jl	PIXEL
        
        lodsd
        mov	bl,ah		; pixel 1
        shr	eax,16
        mov	bh,ah		; pixel 2
        
        bswap	ebx		; store pixels to high hals of EBX.
        
        lodsd
        mov	bh,ah		; pixel 3
        shr	eax,16
        mov	bl,ah		; pixel 4
        
        bswap	ebx		; store pixels to high hals of EBX.
        mov	eax,ebx
        stosd
        
        sub	rcx,4
        jnz	PIXEL4
        jmp	ToEnd
        
PIXEL:	lodsw
	mov	al,ah
	stosb
	loop	PIXEL
        
ToEnd:
        ret                     ; _cdecl return
                
Conv16_8 endp


;*************************************************************************************


        public  Conv16_24
Conv16_24 proc \
        uses rdi rsi
;       Dest:ptr byte,	RCX
;       Src:ptr byte,	RDX
;       count:DWORD	R8

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size
        
        mov     rsi,rdx		;
        
        cld
PIXEL:	lodsw
	mov	[rdi],ah
	inc	rdi
	stosb
	mov	[rdi],ah
	inc	rdi	
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv16_24 endp


;*************************************************************************************

        public  Conv16_32
Conv16_32 proc \
        uses rdi rsi rbx
;       Dest:ptr qword, \
;       Src:ptr byte, \
;       count:DWORD

        mov     rdi,rcx		;
        mov     rcx,R8             ; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; rdi=first pointer
        
        cld
PIXEL:	lodsw
	mov	bx,ax
	rol	eax,16
	mov	ax,bx
	stosd
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv16_32 endp


;*************************************************************************************
;*************************************************************************************


        public  Conv24_8
Conv24_8 proc \
        uses rdi rsi
;       Dest:ptr qword,
;       Src:ptr byte,
;       count:DWORD

        mov     rdi,rcx		; rdi=source pointer 
        mov     rcx,R8             ; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; rsi=destination pointer
        
        add	rsi,2
        cld
PIXEL:	mov	al,[rsi]
        add	rsi,3	
	stosb
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv24_8 endp


;*************************************************************************************

        public  Conv24_16
Conv24_16 proc \
        uses rdi rsi
;       Dest:ptr qword,
;       Src:ptr byte,
;       count:DWORD

        mov     rdi,rcx		; si=source pointer 
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; rdi=destination pointer
        
        inc	rsi
        cld
PIXEL:	mov	al,[rsi]
	inc	rsi
	mov	ah,[rsi]
        add	rsi,2	
	stosw
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv24_16 endp


;*************************************************************************************

        public  Conv24_32
Conv24_32 proc \
        uses rdi rsi
;       Dest:ptr qword,
;       Src:ptr byte,
;       count:DWORD

        mov     rdi,rcx		; si=source pointer 
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; di=destination pointer

        cld
PIXEL:	lodsw
	shl	eax,16		; B2 B1 x x
	lodsb			; B2 B1 x B3
	mov	ah,al		; B2 B1 B3 B3  duplicate last 8 bits
	ror	eax,8		; B3 B2 B1 B3

	stosd
	
	dec	rcx
	jz	ToEnd
	
	lodsb			; x x x B1
	ror	eax,8		; B1 x x x
	lodsw			; B1 x B3 B2
	ror	eax,8		; B2 B1 x B3
	mov	ah,al		; B2 B1 B3 B3	
	ror	eax,8		; B3 B2 B1 B3	
	stosd
	
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv24_32 endp



;*************************************************************************************

        public  Conv24_64
Conv24_64 proc \
        uses rdi rsi
;       Dest:ptr qword,
;       Src:ptr byte,
;       count:DWORD

        mov     rdi,rcx		; si=source pointer 
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; di=destination pointer

        cld
PIXEL:	lodsw			;  x x B2 B1
	mov	dh,ah
	shl	eax,16		; B2 B1 x x
	mov	ah,[rsi]	; B2 B1 B3 x
	mov	al,dh		; B2 B1 B3 B2  << Stored lo DWORD
	mov	dl,ah
	inc	rsi
	
	stosd
	rol	eax,16		; B3 B2 B2 B1
	mov	ah,al		; B3 B2 B1 B1
	mov	al,dl		; B3 B2 B1 B3  << Stored hi DWORD
	stosd

	dec	rcx
	jz	ToEnd
	
	lodsb			; x x x B1
	ror	eax,8		; B1 x x x
	lodsw			; B1 x B3 B2
	mov	dl,al		; B2	
	ror	eax,8		; B2 B1 x B3
	mov	ah,al		; B2 B1 B3 B3
	mov	al,dl		; B2 B1 B3 B2
	mov	dh,ah		; B3	
	stosd
	
	rol	eax,16		; B3 B2 B2 B1
	mov	ah,al		; B3 B2 B1 B1
	mov	al,dh		; B3 B2 B1 B3
	stosd
	
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv24_64 endp


;*************************************************************************************
;*************************************************************************************


        public  Conv32_1
Conv32_1 proc \
        uses rdi rsi rbx
;       Dest:ptr dword, \
;       Src:ptr byte, \
;       count:DWORD

        mov     rdi,rcx		;
        mov     rcx,R8             ; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; di=first pointer
        
        cld        
        mov	bl,1		; add end byte mark
PIXEL:	lodsd
	rol	eax,1		; copy the highest bit to CY
	rcl	bl,1		; transfer bit from CY
	jnc	NoOctet
	mov	[rdi],bl
	inc	rdi
	mov	bl,1		; add end byte mark
	loop	PIXEL
	jmp	toend		; all done here
	
NoOctet:loop	PIXEL

First1:	sal	bl,1		; shift must be finished to 8th bit
	jnc	First1
	mov	[rdi],bl	; store last incomplete byte

toend:
        ret                     ; _cdecl return
                
Conv32_1 endp


;*************************************************************************************


        public  Conv32_4
Conv32_4 proc \
        uses rdi rsi
;       Dest:ptr byte
;       Src:ptr dword
;       count:DWORD

        mov     rdi,rcx		;
        mov     rcx,R8             ; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; di=first pointer
        
        cld
PIXEL:	add	rsi,3
	lodsb			; load 1st hi byte
	and	al,0F0h
	
	dec	rcx
	jnz	NIBBLE2
	stosb			;store incomplete nibble
	jmp	toend

NIBBLE2:mov	ah,al
	add	rsi,3
        lodsb			; load 2nd hi byte
        and	al,0F0h
	ror	al,4
	or	al,ah
	stosb			;store both nibbles
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv32_4 endp



;*************************************************************************************


        public  Conv32_8
Conv32_8 proc \
        uses rdi rsi
;       Dest:ptr qword,
;       Src:ptr byte,
;       count:DWORD

	mov     rdi,rcx		;
        mov     rcx,R8		; rcx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; rsi=first pointer
        
        cld
PIXEL:	add	rsi,3
	movsb
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv32_8 endp


;*************************************************************************************


        public  Conv32_16
Conv32_16 proc \
        uses rdi rsi
;       Dest:ptr qword,
;       Src:ptr byte,
;       count:DWORD

        mov     rdi, rcx	;
        mov     rcx, R8		; rcx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; di=first pointer
        
        cld
PIXEL:	add	rsi,2
	movsw
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv32_16 endp


;*************************************************************************************


        public  Conv32_24
Conv32_24 proc \
        uses rdi rsi
;       Dest:ptr qword
;       Src:ptr byte
;       count:DWORD

        mov     rdi,rcx		;
        mov     rcx,R8             ; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		; di=first pointer
        
        cld
PIXEL:	lodsd

	shr	eax,8
	mov	[rdi],ax
	add	rdi,2
	shr	eax,8
	mov	[rdi],ah
	inc	rdi

	dec	rcx
	jz	ToEnd
	
	lodsd
	shr	eax,8
	mov	[rdi],al
	inc	rdi
	shr	eax,8
	mov	[rdi],ax
        add	rdi,2		

	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv32_24 endp


;*************************************************************************************


        public  Conv32_64
Conv32_64 proc \
        uses rdi rsi
;       Dest:ptr qword,
;       Src:ptr byte,
;	count:DWORD

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,R8		; cx=amount of pixels
        jrcxz	toend		; array has zero size

        mov     rsi,rdx		;
        
        cld
PIXEL:	lodsd
	stosd
	stosd
	loop	PIXEL
        
toend:
        ret                     ; _cdecl return
                
Conv32_64 endp



;########################################################################################
;########################################################################################
;########################################################################################

	public  Flip1
Flip1	proc \
        uses rdi rsi,
;       Data:ptr byte,	RCX
;       count:DWORD	RDX
        
;	mov	rdx, [count]	; RDX already contains [count]
	cmp	rdx, 1
        jle	ToEnd		; ignore values 0 and 1
        dec	rdx
        
	mov	rdi, rcx	; [data]
        mov	cx, dx
	shr	rdx, 3
	mov	rsi, rdi	; first byte pointer
	add	rdi, rdx	; last byte pointer
	
	and	cx, 7
	
	mov	ax, 8080h	; shift mask
	shr	ah, cl		; upper mask 2 in cl
	
	cmp	rdi, rsi
	mov	cl, BYTE ptr [rsi]	;cl should be prepared for shortened loop
	je	LoopMidFlip
	
	mov	ch, BYTE ptr [rdi]		
LoopFlip:
	test	al, cl
	jz	FirstZero
	
	test	ah, ch	
	jnz	BitFlipped		; both bits are 1, nothing to do
	
	or	ch, ah			; set tail bit to 1 (use cached ch)
	xor	cl, al			; XOR will reset bite set - set front bit to 0	
	jmp	BitFlipped
	
FirstZero:
	test	ah, ch
	jz	BitFlipped		; both bits are 0, nothing to do
	
	or	cl, al	
	xor	ch, ah			; XOR will reset bite set

BitFlipped:
	ror	al,1
	jnc	NoIncFront
	
	rol	ah,1
	jnc	FrontNoTail		; No ptr change, continue in loop
	
	mov	BYTE ptr [rsi], cl	; flush both ends
	mov	BYTE ptr [rdi], ch
	dec	rdi			; increment on carry
	inc	rsi
	mov	cl, BYTE ptr [rsi]
	mov	ch, BYTE ptr [rdi]
	cmp	rsi, rdi
	jb	LoopFlip		; begin before tail continue loop rsi<rdi
	ja	ToEnd			; begin after tail - finished
	jmp	LoopMidGo
	
FrontNoTail:		
	mov	BYTE ptr [rsi], cl	; flush both ends	
	inc	rsi			; increment on carry
	mov	cl, BYTE ptr [rsi]	
	cmp	rsi, rdi
	jb	LoopFlip		; continue in looping rsi<rdi; begin is before tail

	mov	BYTE ptr [rdi], ch	; we must store ch to [rdi] because of possible finish
	ja	ToEnd			; begin after tail - finished
	mov	cl, ch			; the value pointed by [rsi] is be overwritten during [rdi],ch; note rdi==rsi.
	jmp	LoopMidGo
	
NoIncFront:	
	rol	ah,1
	jnc	LoopFlip		; We can continue in loop as far as no byte progress.
		
	mov	BYTE ptr [rdi], ch
	dec	rdi			; decrement on carry	
	mov	ch, BYTE ptr [rdi]
	cmp	rsi, rdi
	jb	LoopFlip		; begin before tail continue loop rsi<rdi
	mov	BYTE ptr [rsi], cl	; we must store cl to [rsi] because of possible finish
	ja	ToEnd			; begin after tail - finished	

LoopMidGo:
	cmp	al, ah			; bit mask must be compared
	jbe	ToEnd			; ah<al unsigned - finish
	
	; **************** begin==tail *******************
	
LoopMidFlip:
	test	al, cl
	jz	FirstMidZero
	
	test	ah, cl
	jnz	BitMidFlipped		; both bits are 1, nothing to do
	
	or	cl, ah			; set tail bit to 1 (use cached ch)
	xor	cl, al			; set front bit to 0
	jmp	BitMidFlipped
	
FirstMidZero:
	test	ah, cl
	jz	BitMidFlipped		; both bits are 0, nothing to do
	
	or	cl, al
	xor	cl, ah			; set tail bit to 0

BitMidFlipped:
	ror	al,1	
	rol	ah,1					
					
	cmp	al, ah			; bit mask must be compared
	ja	LoopMidFlip		; ah>al unsigned
	mov	BYTE ptr [rsi], cl

ToEnd:
	ret

Flip1	endp


;*************************************************************************************


	public  Flip4
Flip4	proc \
        uses rdi rsi,
;       Data:ptr byte,	RCX
;       count:DWORD	RDX

        mov     rdi,rcx		; [data] di=first pointer
        mov     rcx,rdx		; [count] cx=amount of pixels
        cmp	rcx,1		; 1 or less pixels makes no sense to flip
        jle	ToEnd		; ignore values 0 and 1

        mov     rsi,rdi		;
        
        shr	rcx,1		; divide 2       
        jc	PixOdd
        
	add	rsi,rcx		; pixel count is even
        dec	rsi
        
        cmp	rdi,rsi
        je	LastNibble	; This can occur for size=2.
LoopEven:mov	al,[rdi]	; Process first byte with nibbles
	rol	al,4		; this shift flips nibbles	

	mov	dl,[rsi]	; Process second byte with nibbles
	rol	dl,4

	mov	[rsi],al
	mov	[rdi],dl

	dec	rsi
	inc	rdi
	cmp	rdi,rsi
	jb	LoopEven	; rsi<rdi
	jne	ToEnd		; No one byte nible needs to be flipped.
LastNibble:
	mov	al,[rdi]
	rol	al,4
	mov	[rdi],al	; Last byte needs to flip nibbles.	
	jmp	ToEnd

                
PixOdd:	add	rsi,rcx		; pixel count is odd i.e. >=3.
LoopOdd:mov	al,[rdi]
	mov	ah,al
	and	ax,0F00Fh
	
	mov	dl,[rsi]
	mov	dh,dl
	and	dx,0FF0h	
		
	or	ax,dx
	;mov	[rdi],al	; nibble 1 flipped with nibble n - no need to store here	
	mov	[rsi],ah	; nibble n flipped with nibble 1

	dec	rsi
	cmp	rsi,rdi
	je	ToEndStore
	
	mov	ah,al		; contained in [rdi]
	and	ax,0F00Fh	
	
	mov	dl,[rsi]
	mov	dh,dl
	and	dx,0FF0h
	
	or	ax,dx
	mov	[rdi],ah	; nibble 2 flipped with nibble n-1		
	mov	[rsi],al	; nibble n-1 flipped with nibble 2

	inc	rdi	
	cmp	rdi,rsi
	jb	LoopOdd

ToEnd:
        ret                     ; _cdecl return
        
ToEndStore:
	mov	[rdi],al	; nibble 1 flipped with nibble n	
        ret                     ; _cdecl return
                
Flip4 endp


;*************************************************************************************


	public  Flip8
Flip8	proc \
        uses rdi rsi
;       Data:ptr byte,	RCX
;       count:DWORD	RDX

        mov     rdi,rcx		; rdi=first pointer
        sub	rdx,1		; rdx=amount of pixels
        jle	ToEnd		; ignore values 0 and 1

        mov     rsi,rdi
        
        add	rsi,rdx

			; The 16bit speedup trick does not work, use classic BYTE exchange.
PIXEL:	mov	al,[rdi]
	mov	ah,[rsi]
	mov	[rdi],ah
	mov	[rsi],al
	inc	rdi
	dec	rsi
	cmp	rdi,rsi
	jl	PIXEL
ToEnd:
        ret                     ; _cdecl return

Flip8 endp


;*************************************************************************************


	public  Flip16
Flip16	proc \
        uses rdi rsi
;       Data:ptr byte,	RCX
;       count:DWORD	RDX

        mov     rdi,rcx		; rdi=first pointer        
        sub	rdx, 1		; rdx=amount of pixels - 1, set flags
        jle	ToEnd		; ignore values 0 and 1

        mov     rsi,rdi		; rsi last pixel position
        
        add	rsi,rdx
        add	rsi,rdx
                
PIXEL:	mov	ax,[rdi]
	mov	cx,[rsi]
	mov	[rdi],cx
	mov	[rsi],ax
	add	rdi,2
	sub	rsi,2
	cmp	rdi,rsi
	jl	PIXEL	

ToEnd:
        ret                     ; _cdecl return
                
Flip16 endp


;*************************************************************************************


	public  Flip24
Flip24	proc \
        uses rdi rsi
;       Data:ptr byte,	RCX
;       count:DWORD	RDX

        mov     rdi,rcx		; rdi=first pointer
        mov     rcx,rdx		; cx=amount of pixels
        cmp	rcx,1
        jle	ToEnd		; ignore values 0 and 1

        mov     rsi,rdi
        
        dec	rcx
        add	rsi,rcx
        add	rsi,rcx
        add	rsi,rcx		; 3*(size-1)        
                
PIXEL:	mov	al,[rdi]	; byte 1
        mov	cl,[rsi]
        mov	[rdi],cl
        mov	[rsi],al
        
        inc	rdi
        inc	rsi
        mov	al,[rdi]	; byte 2
        mov	cl,[rsi]
        mov	[rdi],cl
        mov	[rsi],al
        
        inc	rdi
        inc	rsi
        mov	al,[rdi]	; byte 3
        mov	cl,[rsi]
        mov	[rdi],cl
        mov	[rsi],al
        
        inc	rdi
        sub	rsi,5		; move to previous pixel +2 needs to shift -3 ...  ofs -5
	
	cmp	rdi,rsi
	jb	PIXEL		; unsigned comparison	

ToEnd:
        ret                     ; _cdecl return
                
Flip24 endp


;*************************************************************************************


	public  Flip32
Flip32	proc \
        uses rdi rsi
;       Data:ptr byte,	RCX
;       count:DWORD	RDX

        mov     rdi,rcx		; rdi=first pointer
        sub	rdx,1		; rdx=amount of pixels - 1, set flags
        jle	ToEnd		; ignore values 0 and 1
        
        mov     rsi,rdi		; rsi last pixel position
	
        shl	rdx, 2		; count*4 - 4
        add	rsi,rdx
                
PIXEL:	mov	eax,[rdi]
	mov	ecx,[rsi]
	mov	[rdi],ecx
	mov	[rsi],eax
	add	rdi,4
	sub	rsi,4
	cmp	rdi,rsi
	jl	PIXEL	

ToEnd:
        ret                     ; _cdecl return
                
Flip32	endp


;*************************************************************************************


	public  Flip64
Flip64	proc \
        uses rdi rsi
;       Data:ptr byte,	RCX
;       count:DWORD	RDX

        mov     rdi,rcx		; rdi=first pointer
        sub	rdx, 1		; rdx=amount of pixels - 1, set flags
        jle	ToEnd		; ignore values 0 and 1
	
        mov     rsi, rdi

	shl	rdx, 3		; count*8 - 8
        add	rsi,rdx
       
PIXEL:       
       	mov	rax,[rdi]
       	mov	rcx,[rsi]
	mov	[rsi],rax
	mov	[rdi],rcx	; stosq is slower than this :(
	add	rdi,8	
	sub	rsi,8

	cmp	rdi,rsi
	jl	PIXEL	
ToEnd:
        ret                     ; _cdecl return
                
Flip64	endp


        end
