.486              ;Target processor.  Use instructions for Pentium class machines
.MODEL FLAT, C    ;Use the flat memory model. Use C calling conventions

.CODE             ;Indicates the start of a code segment.


;void RGB_BGR(unsigned char *Data, unsigned PixelCount)
	public	RGB_BGR
RGB_BGR proc \
        uses esi ebx, \
        Data:ptr byte, \
        PixelCount:DWORD

	mov     ecx,[PixelCount]	; cx=amount of pixels
	mov     esi,[Data]		; Load data ptr.
	sub	ecx,4
	jl	LoopPix1

LoopPix4:
	mov	eax,[esi]		;[R1, G1, B1, R2]
	mov	ebx,[esi+4]		;[G2, B2, R3, G3]
	mov	[esi+2],al		;R1
	shr	eax,16			;[B1, R2]
	mov	[esi],al		;B1
	mov	[esi+3],bh		;B2
	mov	[esi+5],ah		;R2
	shr	ebx,16			;[R3, G3, 0, 0]
	mov	eax,[esi+8]		;[B3, R4, G4, B4]
	mov	[esi+8],bl		;R3
	mov	[esi+6],al		;B3
	mov	[esi+11],ah		;B4
	shr	eax,16			;[G4, B4, 0, 0]
	mov	[esi+9],ah		;B4
	add	esi,12
	sub	ecx,4
	jae	LoopPix4

LoopPix1:add	ecx,4
	jz	ToEnd			; array has zero size
LoopPix:mov	al,[esi]
	mov	ah,[esi+2]
	mov	[esi],ah
	mov	[esi+2],al
	add	esi,3
	loop	LoopPix

ToEnd:
	ret				; _cdecl return

RGB_BGR	endp


;void RGBA32_BGRiA32(char *Data, int PixelCount)
	public	RGBA32_BGRiA32
RGBA32_BGRiA32 proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

	mov	ecx,[PixelCount]	; cx=amount of pixels
	jecxz	ToEnd			; array has zero size

	mov	esi,[Data]		; Load data ptr.

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

ToEnd:
        ret                     ; _cdecl return

RGBA32_BGRiA32 endp


;void RGBA64_BGRiA64(char *Data, int PixelCount)
	public	RGBA64_BGRiA64
RGBA64_BGRiA64 proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

	mov	ecx,[PixelCount]	; cx=amount of pixels
	jecxz	ToEnd			; array has zero size

	mov	esi,[Data]		; Load data ptr.

LoopPix:mov	ax,[esi]
	mov	dx,[esi+4]
	mov	[esi],dx
	mov	[esi+4],ax
	mov	ax,[esi+6]
	not	ax
	mov	[esi+6],ax
	add	esi,8
	loop	LoopPix

ToEnd:
        ret                     ; _cdecl return
                
RGBA64_BGRiA64 endp


;void RGB_BGR2(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB_BGR2
RGB_BGR2 proc \
        uses esi edi, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; cx=amount of pixels

        mov     esi,[InData]	;
        mov     edi,[OutData]	;

	sub	ecx,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,[esi]	; EDX = G3 R3 B2 G2
	add	esi,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	[edi],edx	;	G3 B3 R2 G2	shipped out
	add	edi,4
	
	stosd			; R4 G4 B4 R3	shipped out
	;mov	[edi],eax	;	(STOSD is slow on AMD, replaced, seems that Intel works reversed)
	;add	edi,4
	
	sub	ecx,4
	jae	LoopPix4

			; Simple loop for 0,1,2,3 pixels (works also for more px)
LoopSimple:
	add	ecx,4		; ecx was -4, correct counter
        jz	ToEnd		; array has zero size
LoopPix:lodsw
	mov	[edi+2],al
	mov	[edi+1],ah
	lodsb
	mov	[edi],al
	add	edi,3
	dec	ecx
	jz	ToEnd
	
	lodsb
	mov	[edi+2],al
	lodsw
	mov	[edi+1],al
	mov	[edi],ah
	add	edi,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 esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; ecx=amount of pixels

        mov     esi,[InData]		; source data
        mov     edi,[OutData]		; destination data
        
        sub	ecx,4
	jl	LoopSimple		; array size < 4

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

	mov	ebx,[esi]		; EBX = ?? B3 G3 R3
	add	esi,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	ecx,4
	jae	LoopPx4

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

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

ToEnd:
	ret				; _cdecl return

RGB32_BGR24 endp



;void BGR_Gray24precise(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	BGR_Gray24precise
BGR_Gray24precise proc \
        uses esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]     ; cx=amount of pixels
        jecxz	ToEnd		; array has zero size

        mov     esi,[InData]	;
        mov     edi,[OutData]	;

LoopPix:movzx	edx,byte ptr[esi]
	imul	edx,4731

	movzx	eax,byte ptr[esi+1]
	imul	eax,46871
	add	edx,eax

	movzx	eax,byte ptr[esi+2]
	imul	eax,13932
	add	eax,edx
	
	add	esi,3

	shr	eax,16
	mov	[edi],al
	mov	[edi+1],al
	mov	[edi+2],al
	add	edi,3
	loop	LoopPix

ToEnd:
        ret			; _cdecl return
                
BGR_Gray24precise endp



;void BGR32_Gray24(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	BGR32_Gray24
BGR32_Gray24 proc \
        uses esi edi, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]     ; cx=amount of pixels
        jecxz	ToEnd		; array has zero size

        mov     esi,[InData]	;
        mov     edi,[OutData]	;

;	cld
LoopPix:
;				; Alternative code reaches 322MPx/s, but the original reaches 387MPx/s
;	lodsd
;	movzx	edx,al
;	movzx	ebx,ah
;	imul	edx,edx,4731
;	shr	eax,8
;	imul	ebx,ebx,46871	
;	movzx	eax,ah
;	add	edx,ebx
;	imul	eax,eax,13932
;	add	eax,edx
	
	movzx	edx,byte ptr[esi]
	imul	edx,4731

	movzx	eax,byte ptr[esi+1]
	imul	eax,46871
	add	edx,eax

	movzx	eax,byte ptr[esi+2]
	imul	eax,eax,13932
	add	eax,edx
	add	esi,4
	
	shr	eax,16	
;	stosb			; this seems to be slower
;	stosb
;	stosb
	mov	[edi],al
	mov	[edi+1],al
	mov	[edi+2],al
	add	edi,3
	loop	LoopPix

ToEnd:
        ret                     ; _cdecl return
                
BGR32_Gray24 endp


;void RGB32_Gray(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB32_Gray
RGB32_Gray proc \
        uses esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

	mov     ecx,[PixelCount]     ; cx=amount of pixels
	jecxz	ToEnd		; array has zero size

	mov     esi,[InData]	;
	mov     edi,[OutData]	;
	
	mov	bl,3
	mov	dh,0

LoopPix:

; 32 bit native algorithm does not bring performance improvement.
	mov	eax,[esi]
	mov	edx,eax
	add	al,ah
	setc	ah
	shr	edx,16
	mov	dh,0
	add	ax,dx

; Original alg
;	mov	al,[esi]
;	mov	ah,0
;	mov	dl,[esi+1]
;	add	ax,dx
;	mov	dl,[esi+2]
;	add	ax,dx

	div	bl
	add	esi,4
	stosb
	loop	LoopPix

ToEnd:
        ret                     ; _cdecl return

RGB32_Gray endp


;void RGB_Gray(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB24_Gray8
RGB24_Gray8 proc \
        uses esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

	mov	ecx,[PixelCount]     ; cx=amount of pixels

	mov	esi,[InData]	;
	mov	edi,[OutData]	;

	mov	ebx,3

	sub	ecx,4
	jl	LoopPix1

LoopPix2:
	lodsd			;[R1 G1 B1 R2]
	mov	edx,eax
	shr	edx,16
	add	al,ah
	setc	ah
	add	al,dl
	adc	ah,0
	div	bl
	stosb

	lodsd			;[G2 B2 R3 G3]
	add	al,ah
	setc	ah
	add	al,dh
	mov	edx,eax
	adc	ah,0
	shr	edx,16		;R3 G3 0 0
	div	bl
	stosb
	
	add	dl,dh
	setc	dh

	lodsd			;B3 R4 G4 B4
	xchg	bh,ah		;ah=0; bh=R4
	add	ax,dx
	div	bl
	stosb
	
	shr	eax,16		;G4 B4 0 0
	add	al,ah
	setc	ah
	add	al,bh
	adc	ah,0
	mov	bh,0
	div	bl
	stosb

	sub	ecx,4
	jae	LoopPix2

LoopPix1:
	add	ecx,4
	jz	ToEnd		; array has zero size
		
	mov	dh,0

LoopPix:mov	ah,0
	mov	al,[esi]
	mov	dl,[esi+1]
	add	ax,dx
	mov	dl,[esi+2]
	add	ax,dx
	div	bl
	stosb
	add	esi,ebx
	loop	LoopPix

ToEnd:
	ret			; _cdecl return

RGB24_Gray8 endp


;void RGB_Gray24(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB_Gray24
RGB_Gray24 proc \
        uses esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

	mov	ecx,[PixelCount]     ; cx=amount of pixels

	mov	esi,[InData]	;
	mov	edi,[OutData]	;

	mov	ebx,3

	sub	ecx,2
	jl	LoopPix1

LoopPix2:
	lodsw
	add	al,ah
	mov	ah,0
	rcl	ah,1
	mov	dx,[esi]
	add	esi,2
	add	al,dl
	adc	ah,0
	div	bl
	stosb
	stosb
	stosb

	lodsw
	add	al,ah
	mov	ah,0
	rcl	ah,1
	add	al,dh
	adc	ah,0
	div	bl
	stosb
	stosb
	stosb
	
	sub	ecx,2
	ja	LoopPix2
	
LoopPix1:
	add	ecx,2
	cmp	ecx,1
	jl	ToEnd		; array has zero size
		
	mov	dh,0
    
LoopPix:mov	ah,0
	mov	al,[esi]
	mov	dl,[esi+1]
	add	ax,dx
	mov	dl,[esi+2]
	add	ax,dx
	div	bl
	stosb
	stosb
	stosb
	add	esi,ebx
	loop	LoopPix

ToEnd:
	ret			; _cdecl return

RGB_Gray24 endp


;void NotR(char *R, unsigned DataSize)	//R1:=not(R1)
	public  NotR
NotR	proc \       
        R:ptr byte, \
        DataSize:DWORD

        mov     ecx,[DataSize]     ; cx=amount of pixels/bytes
        mov     edx,[R]		; Row byte data

        sub	ecx,4
        jl	LoopPx1
        
LoopPx4:mov	eax,[edx]	; Invert DWORDs
        not	eax	
        mov	[edx],eax
        add	edx,4
        
        sub	ecx,4
        jge	LoopPx4

LoopPx1:add	ecx,4
	jz	ToEnd
	
LoopPix:not	byte ptr [edx]	; Invert BYTE
	inc	edx
	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 edi esi ebx, \
        OutData: ptr BYTE, \
        y: ptr BYTE, \
        u: ptr BYTE, \
	v: ptr BYTE, \
	PixelCount: DWORD
	
	mov	edi,[OutData]
	mov	esi,[y]
	mov	ebx,[u]
	mov	ecx,[PixelCount]
	push	ebp
	mov	ebp,[v]
	
	sub	ecx,2
	jb	Exit

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

	movzx	eax,byte ptr [ebp]	; V
	sub	eax,128	
	imul	eax,291		; 291*V	
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormR1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR1:	mov	[edi],ah	; R1

	movzx	eax,byte ptr [ebx]	; U
	sub	eax,128
	imul	eax,521		; 291*V	
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormB1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax	
NormB1:	mov	[edi+2],ah	; B1

				;EDX = 255*Y
	movzx	eax,byte ptr [ebp]	; V
	sub	eax,128	
	imul	eax,148
	sub	edx,eax

	movzx	eax,byte ptr [ebx]	; U
	sub	eax,128
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V
	
	test	edx,0FFFF0000h
	jz	NormG1
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx	
NormG1:	mov	[edi+1],dh	; G1	

	inc	esi	

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

	movzx	eax,byte ptr [ebp]	; V
	sub	eax,128	
	imul	eax,291		; 291*V	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR2:	mov	[edi+3],ah	; R2	

	movzx	eax,byte ptr[ebx]	; U
	sub	eax,128
	imul	eax,521		; 291*V	
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormB2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormB2:	mov	[edi+5],ah	; B2

				;EDX = 255*Y
	movzx	eax,byte ptr [ebp]	; V
	sub	eax,128	
	imul	eax,148
	sub	edx,eax

	movzx	eax,byte ptr [ebx]	; U
	sub	eax,128
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V

	test	edx,0FFFF0000h
	jz	NormG2
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx
NormG2:	mov	[edi+4],dh	; G2

	add	edi,6

	inc	ebx		; inc U every 2nd pixel
	inc	ebp		; inc V every 2nd pixel

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

Exit:	
	pop	ebp
	ret
YUV_RGB endp


;void YUYV_RGB(unsigned char *OutData, const unsigned char *yuyv, unsigned PixelCount);
	public YUYV_RGB
YUYV_RGB proc \
        uses edi esi ebx ebp, \
        OutData: ptr BYTE, \
        yuyv: ptr BYTE, \
	PixelCount: DWORD
	
	mov	edi,[OutData]
	mov	esi,[yuyv]
	mov	ecx,[PixelCount]	
	
	sub	ecx,2
	jb	Exit

LoopPx:	mov	ebx,[esi]	; YUYV
	
	xor	edx,edx
	mov	dh,bl		; 255*Y		

	mov	eax,ebx
	rol	eax,8
	and	eax,0FFh	; V

	sub	eax,128
	mov	ebp,eax		; store V to EBP
	imul	eax,291		; 291*V	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR1:	mov	[edi],ah	; R1

	movzx	eax,bh		; U

	sub	eax,128
	imul	eax,521		; 291*U	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormB1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax	
NormB1:	mov	[edi+2],ah	; B1

				; EDX = 255*Y	
	imul	eax,ebp,148	; V normalised *148
	sub	edx,eax

        movzx	eax,bh		; U
	sub	eax,128
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V
	
	test	edx,0FFFF0000h
	jz	NormG1
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx	
NormG1:	mov	[edi+1],dh	; G1	

		; 2nd pixel
	mov	edx,ebx
	ror	edx,8
	and	edx,0FF00h	; 255*Y2
	
	imul	eax,ebp,291	; 291*V	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR2:	mov	[edi+3],ah	; R2

	movzx	ebx,bh		; U
	sub	ebx,128	
	imul	eax,ebx,521	; 521*U
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormB2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormB2:	mov	[edi+5],ah	; B2

				;EDX = 255*Y	
	imul	eax,ebp,148	; V normalised * 148
	sub	edx,eax

	imul	eax,ebx,102	; 102*U normalised
	sub	edx,eax		; 255*Y - 102*U - 148*V

	test	edx,0FFFF0000h
	jz	NormG2
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx
NormG2:	mov	[edi+4],dh	; G2

	add	esi,4		; inc Y per 2 pixels
	add	edi,6		; Shift to new pixel R3
	sub	ecx,2
	jae	LoopPx

Exit:
	ret
YUYV_RGB endp


;void UYVY_RGB(unsigned char *OutData, const unsigned char *yuyv, unsigned PixelCount);
	public UYVY_RGB
UYVY_RGB proc \
        uses edi esi ebx ebp, \
        OutData: ptr BYTE, \
        yuyv: ptr BYTE, \
	PixelCount: DWORD
	
	mov	edi,[OutData]
	mov	esi,[yuyv]
	mov	ecx,[PixelCount]	
	
	sub	ecx,2
	jb	Exit

LoopPx:	mov	ebx,[esi]	; Y2_V_Y1_U
	
	xor	edx,edx
	mov	dh,bh		; 255*Y		

	mov	eax,ebx
	bswap	eax
	movzx	eax,ah		; V

	sub	eax,128
	mov	ebp,eax		; store V to EBP
	imul	eax,291		; 291*V	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR1:	mov	[edi],ah	; R1

	movzx	eax,bl		; U

	sub	eax,128
	imul	eax,521		; 291*U	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormB1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax	
NormB1:	mov	[edi+2],ah	; B1

				; EDX = 255*Y	
	imul	eax,ebp,148	; V normalised *148
	sub	edx,eax

        movzx	eax,bl		; U
	sub	eax,128
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V
	
	test	edx,0FFFF0000h
	jz	NormG1
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx	
NormG1:	mov	[edi+1],dh	; G1	

		; 2nd pixel
	mov	edx,ebx
	ror	edx,16
	and	edx,0FF00h	; 255*Y2
	
	imul	eax,ebp,291	; 291*V	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR2:	mov	[edi+3],ah	; R2

	movzx	ebx,bl		; U
	sub	ebx,128	
	imul	eax,ebx,521	; 521*U
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormB2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormB2:	mov	[edi+5],ah	; B2

				;EDX = 255*Y	
	imul	eax,ebp,148	; V normalised * 148
	sub	edx,eax

	imul	eax,ebx,102	; 102*U normalised
	sub	edx,eax		; 255*Y - 102*U - 148*V

	test	edx,0FFFF0000h
	jz	NormG2
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx
NormG2:	mov	[edi+4],dh	; G2

	add	esi,4		; inc Y per 2 pixels
	add	edi,6		; Shift to new pixel R3
	sub	ecx,2
	jae	LoopPx

Exit:
	ret
UYVY_RGB endp


;void YVYU_RGB(unsigned char *OutData, const unsigned char *yuyv, unsigned PixelCount);
	public YVYU_RGB
YVYU_RGB proc \
        uses edi esi ebx, \
        OutData: ptr BYTE, \
        yuyv: ptr BYTE, \
	PixelCount: DWORD
	
	mov	edi,[OutData]
	mov	esi,[yuyv]
	mov	ecx,[PixelCount]
	push	ebp	
	
	sub	ecx,2
	jb	Exit

LoopPx:	mov	ebx,[esi]	; YVYU
	
	xor	edx,edx
	mov	dh,bl		; 255*Y		

	movzx	eax,bh		; V

	sub	eax,128
	mov	ebp,eax		; store V to EBP
	imul	eax,291		; 291*V	
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormR1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR1:	mov	[edi],ah	; R1

	mov	eax,ebx
	rol	eax,8
	and	eax,0FFh	; U

	sub	eax,128
	imul	eax,521		; 291*U	
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormB1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax	
NormB1:	mov	[edi+2],ah	; B1	

				;EDX = 255*Y	
	imul	eax,ebp,148	; V normalised *148
	sub	edx,eax

        mov	eax,ebx
	rol	eax,8
	and	eax,0FFh	; U
	sub	eax,128
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V

	test	edx,0FFFF0000h
	jz	NormG1
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx	
NormG1:	mov	[edi+1],dh	; G1

		; 2nd pixel
	mov	edx,ebx
	ror	edx,8
	and	edx,0FF00h	; 255*Y2
	
	imul	eax,ebp,291	; 291*V	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR2:	mov	[edi+3],ah	; R2

	rol	ebx,8
	and	ebx,0FFh	; U
	sub	ebx,128	
	imul	eax,ebx,521	; 521*U
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormB2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormB2:	mov	[edi+5],ah	; B2

				;EDX = 255*Y	
	imul	eax,ebp,148	; V normalised * 148
	sub	edx,eax

	imul	eax,ebx,102	; 102*U normalised
	sub	edx,eax		; 255*Y - 102*U - 148*V

	test	edx,0FFFF0000h
	jz	NormG2
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx
NormG2:	mov	[edi+4],dh	; G2

	add	esi,4		; inc Y per 2 pixels
	add	edi,6		; Shift to new pixel R3
	sub	ecx,2
	jae	LoopPx

Exit:	
	pop	ebp
	ret
YVYU_RGB endp


;void AYUV_BGR24(unsigned char *pDst, const unsigned char *ayuv, unsigned Pixels);
        public  AYUV_BGR24
AYUV_BGR24 proc \
        uses edi esi ebx ebp, \
        OutData: ptr BYTE, \
        yuyv: ptr BYTE, \
	PixelCount: DWORD
	
	mov	edi,[OutData]
	mov	esi,[yuyv]
	mov	ecx,[PixelCount]	
	jecxz	Exit

LoopPx:	mov	ebx,[esi]		; AYUV
	
	xor	edx,edx
	mov	dh,bh			; 255*Y		

	rol	ebx,16
	
	movzx	eax,bh			; V
	sub	eax,128
	mov	ebp,eax			; store V to EBP
	imul	eax,291			; 291*V	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR1:	mov	[edi+2],ah		; R

	movzx	eax,bl			; U

	sub	eax,128
	imul	eax,521			; 291*U	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormB1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax	
NormB1:	mov	[edi],ah		; B

				; EDX = 255*Y	
	imul	eax,ebp,148		; V normalised *148
	sub	edx,eax

        movzx	eax,bl			; U
	sub	eax,128
	imul	eax,102			; 102*U
	sub	edx,eax			; 255*Y - 102*U - 148*V
	
	test	edx,0FFFF0000h
	jz	NormG1
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx	
NormG1:	mov	[edi+1],dh		; G

	add	esi,4			; inc Y per pixel
	add	edi,3			; Shift to new pixel R3
	dec	ecx
	jnz	LoopPx

Exit:
	ret
AYUV_BGR24 endp


;---------------------------------------------------------------


;void swab16(unsigned char *Data, unsigned PixelCount)
	public	swab16
swab16 proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; cx=amount of pixels
	mov	esi,[Data]		; Load data ptr.

        sub	ecx,2
	jl	LoopPx1

LoopPx2:mov	eax,[esi]
	bswap	eax
	rol	eax,16
	mov	[esi],eax
	add	esi,4
        sub	ecx,2
	ja	LoopPx2

LoopPx1:add	ecx,2
	jz	ToEnd		; array has zero size

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

ToEnd:
	ret                     ; _cdecl return
swab16	endp



;void swab32(unsigned char *Data, unsigned PixelCount)
	public	swab32
swab32 proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; cx=amount of pixels
        jecxz	ToEnd			; array has zero size

	mov	esi,[Data]		; Load data ptr.

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

ToEnd:
	ret                     ; _cdecl return
swab32	endp



;void swab64(unsigned char *Data, unsigned PixelCount)
	public	swab64
swab64 proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; cx=amount of pixels
        jecxz	ToEnd			; array has zero size

	mov	esi,[Data]		; Load data ptr.

LoopPix:mov	eax,[esi]
	mov	edx,[esi+4]
	bswap	eax
	bswap	edx
	mov	[esi+4],eax
	mov	[esi],edx
	add	esi,8
	loop	LoopPix

ToEnd:
	ret                     ; _cdecl return
swab64	endp


;void DiffVer1_u32(uint32_t *Out, const uint32_t *In, const uint32_t *In2, int SizeX);
	public	DiffVer1_u32
DiffVer1_u32 proc \
        uses edi ebx esi, \
        OutL: ptr DWORD, \
        InL: ptr DWORD, \
	In2L: ptr DWORD, \
	SizeX: DWORD

	mov	edi,[OutL]
	or	edi,edi
	jz	DiffV1E
	mov	esi,[InL]
	or	esi,esi
	jz	DiffV1E
	mov	edx,[In2L]
	or	edx,edx
	jz	DiffV1E
	mov	ecx,[SizeX]
	jecxz	DiffV1E	
DiffV11:mov	eax,[esi]
	stc
	rcr	eax,1
	add	esi,4
	mov	ebx,[edx]
	shr	ebx,1
	sub	eax,ebx
	add	edx,4
	mov	[edi],eax
	add	edi,4
	loop	DiffV11
DiffV1E:ret
DiffVer1_u32 endp


        end
