
.CODE             ;Indicates the start of a code segment.


;void RGB_BGR(unsigned char *Data, unsigned PixelCount)
	public	RGB_BGR

RGB_BGR proc \
        uses rsi
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	mov	rsi,rcx		; Load data ptr.
        mov     rcx,rdx		; rcx=amount of pixels
        jrcxz	ToEnd		; array has zero size

LoopPix:mov	al,[rsi]
	mov	ah,[rsi+2]
	mov	[rsi],ah
	mov	[rsi+2],al
	add	rsi,3
	loop	LoopPix

ToEnd:
        ret                     ; _cdecl return
                
RGB_BGR	endp



;void RGBA32_BGRA32(char *Data, int PixelCount)
	public	RGBA32_BGRiA32

RGBA32_BGRiA32 proc \
        uses rsi
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	mov	rsi,rcx		; Load data ptr.
        mov     rcx,rdx		; rcx=amount of pixels
        jrcxz	ToEnd		; array has zero size

LoopPix:mov	al,[rsi]
	mov	ah,[rsi+2]
	mov	[rsi],ah
	mov	[rsi+2],al
	mov	al,[rsi+3]
	not	al
	mov	[rsi+3],al
	add	rsi,4
	loop	LoopPix

ToEnd:
        ret                     ; _cdecl return
                
RGBA32_BGRiA32 endp



;void RGB_BGR2(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB_BGR2
RGB_BGR2 proc \
        uses rsi rdi
;       OutData: ptr byte,RCX
;       InData: ptr byte,RDX
;       PixelCount: QWORD R8

	mov	rsi,rdx
	mov	rdi,rcx

        mov     rcx,R8		; cx=amount of pixels

	sub	rcx,4
	jl	LoopSimple

		; Processing of 4px block with size 3xDWORD	
LoopPix4:lodsd			; EAX = R2 B1 G1 R1
	bswap	eax		; EAX = R1 G1 B1 R2
	
	mov	edx,[rsi]	; EDX = G3 R3 B2 G2
	add	rsi,4
	
	xchg	al,dh		; EAX = R1 G1 B1 B2, EDX=G3 R3 R2 G2
	ror	eax,8		; EAX = B2 R1 G1 B1 
	stosd			;	B2 R1 G1 B1	shipped out
	
	lodsd			; EAX = B4 G4 R4 B3
	bswap	eax		; EAX = B3 R4 G4 B4
	rol	eax,8		; EAX = R4 G4 B4 B3
	
	ror	edx,8		; EDX = G2 G3 R3 R2
	xchg	dh,al		;  B3 <-> R3	    , EAX=R4 G4 B4 R3
	rol	edx,8		; EDX = G3 B3 R2 G2
	
	mov	[rdi],edx	;	G3 B3 R2 G2	shipped out
	add	rdi,4

	stosd			; R4 G4 B4 R3	shipped out
	
	sub	rcx,4
	jae	LoopPix4

			; Simple loop for 0,1,2,3 pixels (works also for more px)
LoopSimple:
	add	rcx,4		; rcx was -4, correct counter
        jz	ToEnd		; array has zero size

LoopPix:lodsw
	mov	[rdi+2],al
	mov	[rdi+1],ah
	lodsb
	mov	[rdi],al
	add	rdi,3
	dec	rcx
	jz	ToEnd
	
	lodsb
	mov	[rdi+2],al
	lodsw
	mov	[rdi+1],al
	mov	[rdi],ah
	add	rdi,3
	
	loop	LoopPix
ToEnd:	ret
	
RGB_BGR2 endp		



;void RGB32_BGR24(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB32_BGR24
RGB32_BGR24 proc \
        uses rsi rdi rbx
;       OutData: ptr byte,RCX
;       InData: ptr byte,RDX
;       PixelCount: QWORD R8

        mov     rsi,rdx			; source data
        mov     rdi,rcx			; destination data

	mov     rcx,R8			; rcx=amount of pixels

        sub	rcx,4
	jl	LoopSimple		; array size < 4

LoopPx4:mov	ebx,[rsi]		; EBX = ?? B1 G1 R1
	add	rsi,4
	bswap	ebx			; EBX = R1 G1 B1 ??
		
;	lodsd				; EAX = ?? B2 G2 R2
	mov	eax,[rsi]
	add	esi,4
	bswap	eax			; EAX = R2 G2 B2 ??
	
	mov	bl,ah			; BL = B2
	ror	ebx,8			; EBX = B2 R1 G1 B1	
	mov	[rdi],ebx		;	shipout B2 R1 G1 B1
	add	rdi,4

	mov	ebx,[rsi]		; EBX = ?? B3 G3 R3
	add	rsi,4
	mov	dl,bl			; DL = R3
	
	mov	ah,bh			; EAX = R2 G2 G3 ??
	bswap	ebx			; EBX = R3 G3 B3 ??
	mov	al,bh			; EAX = R2 G2 G3 B3
	ror	eax,16			; EAX = G3 B3 R2 G2
	stosd				;	shipout G3 B3 R2 G2
	
	lodsd				; EAX = ?? B4 G4 R4
	bswap	eax			; EAX = R4 G4 B4 ??
	mov	al,dl			; EAX = R4 G4 B4 R3
	
	stosd				;	shipout R4 G4 B4 R3

	sub	rcx,4
	jae	LoopPx4

LoopSimple:
	add	rcx,4
	jz	ToEnd			; remaining size = 0

LoopPix:lodsd
	mov	[rdi+2],al
	mov	[rdi+1],ah
	shr	eax,8
	mov	[rdi],ah
	add	rdi,3
	loop	LoopPix

ToEnd:
        ret                     ; _cdecl return
                
RGB32_BGR24 endp


;void NotR(char *R, unsigned DataSize)	//R1:=not(R1)
	public  NotR
NotR	proc \
        uses rdi
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	mov	rdi,rcx
        mov     rcx,rdx		; rcx=amount of pixels/bytes
        
        sub	rcx,8
        jl	LoopPx1
        
LoopPx8:mov	rax,[rdi]	; Invert QWORDs
        not	rax
        mov	[rdi],rax
        add	rdi,8
        
        sub	rcx,8
        jge	LoopPx8

LoopPx1:add	rcx,8
	jz	ToEnd

LoopPix:mov	al,[rdi]	; Invert BYTEs
	not	al
	mov	[rdi],al
	inc	rdi
	loop	LoopPix
ToEnd:
        ret                     ; _cdecl return
                
NotR	endp



;void YUV_RGB(unsigned char *OutData, const unsigned char *y, const unsigned char *u, const unsigned char *v, unsigned PixelCount)
	public YUV_RGB
YUV_RGB proc \
        uses rdi rsi rbx,
        OutData: ptr BYTE, \
        y: ptr BYTE, \
        u: ptr BYTE, \
	v: ptr BYTE, \
	PixelCount: DWORD	; on stack

	
	mov	rdi,rcx		; [OutData]
	mov	rsi,rdx		; [y]
	mov	ecx,PixelCount
;	mov	ecx,[rsp+28h+4*8]	;28h stays for 5th arg; rbp,rdi,rsi,rbx are now on the stack

	sub	ecx,2
	jb	exit

LoopPx:	xor	edx,edx
	mov	dh,[rsi]	; 255*Y	

	xor	eax,eax
	mov	al,[R9]		; V
	sub	eax,128
	mov	R10,rax	
	imul	eax,291		; 291*V	
	add	eax,edx
	
	js	SmallR1
	test	eax,0FFFF0000h
	jnz	BigR1
	mov	[rdi],ah	; B1
	jmp	LoopX1R
BigR1:	mov	byte ptr [rdi],255
        jmp	LoopX1R
SmallR1:mov	byte ptr [rdi],0
LoopX1R:add	rdi,2		; Shift to B

	xor	eax,eax
	mov	al,[R8]		; U
	sub	eax,128
	mov	R11,rax
	imul	eax,521		; 291*V	
	add	eax,edx

	js	SmallB1
	test	eax,0FFFF0000h
	jnz	BigB1
	mov	[rdi],ah	; B1
	jmp	LoopX1B
BigB1:	mov	byte ptr [rdi],255
        jmp	LoopX1B
SmallB1:mov	byte ptr [rdi],0
LoopX1B:dec	rdi		; Shift back to G1

				;EDX = 255*Y
	mov	rax,R10		; V	
	imul	eax,148
	sub	edx,eax
	
	mov	rax,R11		; U
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V

	js	SmallG1
	test	edx,0FFFF0000h
	jnz	BigG1
	mov	[rdi],dh	; R1
	jmp	LoopX1G
BigG1:	mov	byte ptr [rdi],255
        jmp	LoopX1G
SmallG1:mov	byte ptr [rdi],0
LoopX1G:add	rdi,2		; Shift to R2

	inc	rsi	

		; 2nd pixel
	xor	edx,edx
	mov	dh,[rsi]	; 255*Y		

	mov	rax,R10		; V	
	imul	eax,291		; 291*V	
	add	eax,edx
	
	js	SmallR2
	test	eax,0FFFF0000h
	jnz	BigR2
	mov	[rdi],ah	; B2
	jmp	LoopX2R
BigR2:	mov	byte ptr [rdi],255
        jmp	LoopX2R
SmallR2:mov	byte ptr [rdi],0
LoopX2R:add	rdi,2		; Shift to B2

	mov	rax,R11		; U
	imul	eax,521		; 521*U	
	add	eax,edx

	js	SmallB2
	test	eax,0FFFF0000h
	jnz	BigB2
	mov	[rdi],ah	; B1
	jmp	LoopX2B
BigB2:	mov	byte ptr [rdi],255
        jmp	LoopX2B
SmallB2:mov	byte ptr [rdi],0
LoopX2B:dec	rdi		; Shift back to G

				;EDX = 255*Y
	mov	rax,R10		; V	
	imul	eax,148
	sub	edx,eax
	
	mov	rax,R11		; U
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V

	js	SmallG2
	test	edx,0FFFF0000h
	jnz	BigG2
	mov	[rdi],dh	; R1
	jmp	LoopX2G
BigG2:	mov	byte ptr [rdi],255
        jmp	LoopX2G
SmallG2:mov	byte ptr [rdi],0
LoopX2G:add	rdi,2		; Shift to R3

	inc	R8		; inc U every 2nd pixel
	inc	R9		; inc V every 2nd pixel

	inc	rsi		; inc Y every pixel
	sub	ecx,2
	jae	LoopPx

Exit:	
	ret
YUV_RGB endp


;void swab16(unsigned char *Data, unsigned PixelCount)
	public	swab16

swab16 proc \
        uses rsi
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	mov	rsi,rcx		; Load data ptr.
        mov     rcx,rdx		; rcx=amount of pixels
        jrcxz	ToEnd		; array has zero size

LoopPix:mov	ax,[rsi]
	xchg	ah,al
	mov	[rsi],ax
	add	rsi,2
	loop	LoopPix

ToEnd:
        ret                     ; _cdecl return
                
swab16	endp



;void swab32(unsigned char *Data, unsigned PixelCount)
	public	swab32

swab32 proc \
        uses rsi
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	mov	rsi,rcx		; Load data ptr.
        mov     rcx,rdx		; rcx=amount of pixels        
        jrcxz	ToEnd		; array has zero size

LoopPix:mov	eax,[rsi]
	bswap	eax
	mov	[rsi],eax
	add	rsi,4
	loop	LoopPix

ToEnd:
        ret                     ; _cdecl return
                
swab32	endp



;void swab64(unsigned char *Data, unsigned PixelCount)
	public	swab64

swab64 proc \
        uses rsi
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	mov	rsi,rcx		; Load data ptr.
        mov     rcx,rdx		; rcx=amount of pixels        
        jrcxz	ToEnd		; array has zero size

LoopPix:mov	rax,[rsi]
	bswap	rax
	mov	[rsi],rax
	add	rsi,8
	loop	LoopPix

ToEnd:
        ret                     ; _cdecl return
                
swab64	endp


        end
